DOMdocument search for tag - php

i am trying to do this:
i have several thousand xml files, i am reading them, and i am looking for special text inside an xml with specific tag, but those tags which are having the text i need, are different. what i did till now is this:
$xml_filename = "xml/".$anzeigen_id.".xml";
$dom = new DOMDocument();
$dom->load($xml_filename);
$value = $dom->getElementsByTagName('FormattedPositionDescription');
foreach($value as $v){
$text = $v->getElementsByTagName('Value');
foreach($text as $t){
$anzeige_txt = $t->nodeValue;
$anzeige_txt = utf8_decode($anzeige_txt);
$anzeige_txt = mysql_real_escape_string($anzeige_txt);
echo $anzeige_txt;
$sql = "INSERT INTO joinvision_anzeige(`firmen_id`,`anzeige_id`,`anzeige_txt`) VALUES ('$firma_id','$anzeigen_id','$anzeige_txt')";
$sql_inserted = mysql_query($sql);
if($sql_inserted){
echo "'$anzeigen_id' from $xml_filename inserted<br />";
}else{
echo mysql_errno() . ": " . mysql_error() . "\n";
}
}
}
now what i need to do is this:
look for FormattedPositionDescription in xml and if there is not this tag there, then look for anothertag in that same xml file..
how can i do this, thanks for help in advance

Just check the length property of the DOMNodeList:
$value = $dom->getElementsByTagName('FormattedPositionDescription');
if($value->length > 0)
{
// found some FormattedPositionDescription
}
else
{
// didn't find any FormattedPositionDescription, so look for anothertag
$list = $dom->getElementsByTagName('anothertag');
}

Related

Generating XML from SQL using Mysqli

I'm trying to pull all the data from my users table and display it in XML format. The connection works fine and everything as I have a login and registration set up fine, but I can't seem to get this to display anything other than a white screen.
I've found lots of different tutorials on how to do it with mysql but not mysqli. what am i missing?
generatexml.php
<?php
include 'connection.php';
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
$root_element = $config['users'];
$xml .= "<$root_element>";
if ($result = $mysqli->query("SELECT * FROM users", MYSQLI_USE_RESULT)) {
while($row = $result->fetch_assoc())
{
$xml .= "<".$config['users'].">";
//loop through each key,value pair in row
foreach($result_array as $key => $value)
{
//$key holds the table column name
$xml .= "<$key>";
//embed the SQL data in a CDATA element to avoid XML entity issues
$xml .= "<![CDATA[$value]]>";
//and close the element
$xml .= "</$key>";
}
$xml.="</".$config['users'].">";
echo $xml;
}
}
?>
I struggle a lot to find out this solution in mysqli format but nowhere i found the solution. Below is the solution i figured. Run this demo and map it your requirement, surely it will help.
<?php
//Create file name to save
$filename = "export_xml_".date("Y-m-d_H-i",time()).".xml";
$mysql = new Mysqli('server', 'user', 'pass', 'database');
if ($mysql->connect_errno) {
throw new Exception(sprintf("Mysqli: (%d): %s", $mysql->connect_errno, $mysql->connect_error));
}
//Extract data to export to XML
$sqlQuery = 'SELECT * FROM t1';
if (!$result = $mysql->query($sqlQuery)) {
throw new Exception(sprintf('Mysqli: (%d): %s', $mysql->errno, $mysql->error));
}
//Create new document
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
//add table in document
$table = $dom->appendChild($dom->createElement('table'));
//add row in document
foreach($result as $row) {
$data = $dom->createElement('row');
$table->appendChild($data);
//add column in document
foreach($row as $name => $value) {
$col = $dom->createElement('column', $value);
$data->appendChild($col);
$colattribute = $dom->createAttribute('name');
// Value for the created attribute
$colattribute->value = $name;
$col->appendChild($colattribute);
}
}
/*
** insert more nodes
*/
$dom->formatOutput = true; // set the formatOutput attribute of domDocument to true
// save XML as string or file
$test1 = $dom->saveXML(); // put string in test1
$dom->save($filename); // save as file
$dom->save('xml/'.$filename);
?>
If you have access to the mysql CLI, here's my quick hack for achieving this:
$sql = "SELECT * FROM dockcomm WHERE listname = 'roortoor'
and status IN ('P','E') and comm_type IN ('W','O')
and comm_period NOT IN ('1','2','3','4') order by comment_num";
$cmd = "/usr/bin/mysql -u<person> -h<host> -p<password> <database> --xml -e \"$sql\";";
$res = system($cmd ,$resval);
echo $res;
Here is a solution using php only. You where close to getting it right. This was the key part of the code that I changed "$row as $key => $data" used $row instead of $result_array, ie. iterate through row not the result_array (this contains the entire dataset). Hope this helps someone.
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$value .="<record>\r\n";
//loop through each key,value pair in row
foreach($row as $key => $data)
{
//$key holds the table column name
$vals = "\t" . "<". $key . ">" . "<![CDATA[" . $data . "]]>" . "</" . $key . ">" . "\r\n";
$value = $value . $vals;
//echo $value;
}
$value .="</record>\r\n";
$count++;
}
} else {
// echo "0 results";
}
$conn->close();
One possible issue could be this line:
if ($result = $mysqli->query("SELECT * FROM users", MYSQLI_USE_RESULT)) {
Try the procedural approach instead of the object oriented approach. I do not know if $mysqli is defined in connection.php, but it is possible that you mixed it up.
if ($result = mysqli_query('SELECT * FROM users', MYSQLI_USE_RESULT)) {
This could resolve the white screen error.
I noticed two other things:
(1) One tiny effectiveness issue:
$xml = '<?xml version="1.0" encoding="UTF-8"?>';
So you do not need to escape every single quotation mark.
(2) One serious XML issue: The root element needs to be closed before you echo your $xml.
$xml .= "</$root_element>";
echo $xml;
Generally, for your purpose, it would be safer to use PHP's XMLWriter extension, as already proposed.

How Can i get the child element using class using php DOMXPath?

I want to get the child element with specific class form html I have manage to find the element using tag name but can't figureout how can I get the child emlement with specific class?
Here is my CODE:
<?php
$html = file_get_contents('myfileurl'); //get the html returned from the following url
$pokemon_doc = new DOMDocument();
libxml_use_internal_errors(TRUE); //disable libxml errors
if (!empty($html)) { //if any html is actually returned
$pokemon_doc->loadHTML($html);
libxml_clear_errors(); //remove errors for yucky html
$pokemon_xpath = new DOMXPath($pokemon_doc);
//get all the h2's with an id
$pokemon_row = $pokemon_xpath->query("//li[#class='content']");
if ($pokemon_row->length > 0) {
foreach ($pokemon_row as $row) {
$title = $row->getElementsByTagName('h3');
foreach ($title as $a) {
echo "Title: ";
echo strip_tags($a->nodeValue). '<br>';
}
$links = $row->getElementsByTagName('a');
foreach ($links as $l) {
echo "Link: ";
echo strip_tags($l->nodeValue). '<br>';
}
$desc = $row->getElementsByTagName('span');
//I tried that but didnt work..... iwant to get the span with class desc
//$desc = $row->query("//span[#class='desc']");
foreach ($desc as $d) {
echo "DESC: ";
echo strip_tags($d->nodeValue) . '<br><br>';
}
// echo $row->nodeValue . "<br/>";
}
}
}
?>
Please let me know if this is a duplicate but I cant find out or you think question is not good or not explaining well please let me know in comments.
Thanks.

Buffering or moving PHP data to display in a different part of a webpage

I am parsing a very large XML file with XMLReader.
$reader = new XMLReader;
$reader->open('products.xml');
$dom = new DOMDocument;
$xpath = new DOMXpath($dom);
while ($reader->read() && $reader->name !== 'product') {
continue;
}
A while loop is used to display relevant data based on user input as well as building arrays with XML values.
while ($reader->name === 'product') {
$node = $dom->importNode($reader->expand(), TRUE);
if ($xpath->evaluate('number(price)', $node) > $price_submitted) {
$category = $xpath->evaluate('string(#category)', $node);
$name = $xpath->evaluate('string(name)', $node);
$price = $xpath->evaluate('number(price)', $node);
// Relevant search results displayed here:
echo "Category: " . $category . ". ";
echo "Name: " . $name . ". ";
echo "Price: " . $price . ". ";
$nameArray[] = $name;
}
$reader->next('product');
}
The foreach loop below uses the array that is built in the while loop above. I need these values (displayed in this foreach loop below) to appear BEFORE the while loop above displays the relevant search results. With XMLReader, you can only execute one while loop for each time you parse the XML, and I don't want to parse it twice because of memory and overhead issues. What is the best way to do this?
foreach ($nameArray as $names) {
echo $names . " ";
}
Well… there are not many options. The most effectiv straight-forward approach is to store category/name/price in array instead of outputting them directly:
<?php
$data = array();
while ($reader->name === 'product') {
$node = $dom->importNode($reader->expand(), TRUE);
if ($xpath->evaluate('number(price)', $node) > $price_submitted) {
$category = $xpath->evaluate('string(#category)', $node);
$name = $xpath->evaluate('string(name)', $node);
$price = $xpath->evaluate('number(price)', $node);
$data[] = array($category, $name, $price);
$nameArray[] = $name;
}
$reader->next('product');
}
foreach ($nameArray as $names) {
echo $names . " ";
}
foreach ($data as $datum) {
// Relevant search results displayed here:
echo "Category: " . $datum[0] . ". ";
echo "Name: " . $datum[1] . ". ";
echo "Price: " . $datum[2] . ". ";
}
In case that doesn't work memory-wise (you mentioned that XML file is really large) you should use db- or file-backed temporary storage

how to display data id, name?

My file xml:
<pasaz:Envelope>
<pasaz:Body>
<loadOffe>
<offe>
<off>
<id>120023</id>
<name>my name John</name>
<name>Test</name>
</off>
</offe>
</loadOffe>
</pasaz:Body>
</pasaz:Envelope>
How to view a php (id and name).
If you're just looking for a simple way to extract the contents of a tag, but don't want to go to all the trouble of parsing the XML properly, you could do something like this:
$xml = ""; // your xml data as a string
function get_tag_contents($xml, $tagName) {
$startPosition = strpos($xml, "<" . $tagName . ">");
$endPosition = strpos($xml, "</" . $tagName . ">");
$length = $endPosition - ($startPosition + 1);
return substr($xml, $startPosition, $length);
}
$id = get_tag_contents($xml, "id");
$name = get_tag_contents($xml, "name");
This assumes you haven't assigned any attributes to your tags, and that each tag is unique (in the example you gave us I noted two "name" tags, and if you want both you'll need to make this solution a bit more robust or do proper XML parsing).
How to get all items?
Example (does not work ..)
$pliks = simplexml_load_file("file.xml");
foreach ($pliks->children('pasaz', true) as $body)
{
foreach ($body->children() as $loadOffe)
{
if ($loadOffe->offe->off) {
echo "<p>id: $loadOffe->id</p>";
echo "$id->id";
echo "<p>name: <b>$name->name</b></p>";
}
}
// echo $loadOffe->offe->off->id;
}
As Marc B suggested in his comment you should use DOM, either use getElementsByTagName() or DOMXPath, example for getElementaByTagName():
$dom = new DOMDocument;
$dom->loadXML($xml);
$ids = $dom->getElementsByTagName('id');
if( $ids || !$ids->length){
throw new Exception( 'Id not found');
}
return $ids->item(0);

Need some help with XML parsing

The XML feed is located at: http://xml.betclick.com/odds_fr.xml
I need a php loop to echo the name of the match, the hour, and the bets options and the odds links.
The function will select and display ONLY the matchs of the day with streaming="1" and the bets type "Ftb_Mr3".
I'm new to xpath and simplexml.
Thanks in advance.
So far I have:
<?php
$xml_str = file_get_contents("http://xml.betclick.com/odds_fr.xml");
$xml = simplexml_load_string($xml_str);
// need xpath magic
$xml->xpath();
// display
?>
Xpath is pretty simple once you get the hang of it
you basically want to get every match tag with a certain attribute
//match[#streaming=1]
will work pefectly, it gets every match tag from underneath the parent tag with the attribute streaming equal to 1
And i just realised you also want matches with a bets type of "Ftb_Mr3"
//match[#streaming=1]/bets/bet[#code="Ftb_Mr3"]
This will return the bet node though, we want the match, which we know is the grandparent
//match[#streaming=1]/bets/bet[#code="Ftb_Mr3"]/../..
the two dots work like they do in file paths, and gets the match.
now to work this into your sample just change the final bit to
// need xpath magic
$nodes = $xml->xpath('//match[#streaming=1]/bets/bet[#code="Ftb_Mr3"]/../..');
foreach($nodes as $node) {
echo $node['name'].'<br/>';
}
to print all the match names.
I don't know how to work xpath really, but if you want to 'loop it', this should get you started:
<?php
$xml = simplexml_load_file("odds_fr.xml");
foreach ($xml->children() as $child)
{
foreach ($child->children() as $child2)
{
foreach ($child2->children() as $child3)
{
foreach($child3->attributes() as $a => $b)
{
echo $a,'="',$b,"\"</br>";
}
}
}
}
?>
That gets you to the 'match' tag which has the 'streaming' attribute. I don't really know what 'matches of the day' are, either, but...
It's basically right out of the w3c reference:
http://www.w3schools.com/PHP/php_ref_simplexml.asp
I am using this on a project. Scraping Beclic odds with:
<?php
$match_csv = fopen('matches.csv', 'w');
$bet_csv = fopen('bets.csv', 'w');
$xml = simplexml_load_file('http://xml.cdn.betclic.com/odds_en.xml');
$bookmaker = 'Betclick';
foreach ($xml as $sport) {
$sport_name = $sport->attributes()->name;
foreach ($sport as $event) {
$event_name = $event->attributes()->name;
foreach ($event as $match) {
$match_name = $match->attributes()->name;
$match_id = $match->attributes()->id;
$match_start_date_str = str_replace('T', ' ', $match->attributes()->start_date);
$match_start_date = strtotime($match_start_date_str);
if (!empty($match->attributes()->live_id)) {
$match_is_live = 1;
} else {
$match_is_live = 0;
}
if ($match->attributes()->streaming == 1) {
$match_is_running = 1;
} else {
$match_is_running = 0;
}
$match_row = $match_id . ',' . $bookmaker . ',' . $sport_name . ',' . $event_name . ',' . $match_name . ',' . $match_start_date . ',' . $match_is_live . ',' . $match_is_running;
fputcsv($match_csv, explode(',', $match_row));
foreach ($match as $bets) {
foreach ($bets as $bet) {
$bet_name = $bet->attributes()->name;
foreach ($bet as $choice) {
// team numbers are surrounded by %, we strip them
$choice_name = str_replace('%', '', $choice->attributes()->name);
// get the float value of odss
$odd = (float)$choice->attributes()->odd;
// concat the row to be put to csv file
$bet_row = $match_id . ',' . $bet_name . ',' . $choice_name . ',' . $odd;
fputcsv($bet_csv, explode(',', $bet_row));
}
}
}
}
}
}
fclose($match_csv);
fclose($bet_csv);
?>
Then loading the csv files into mysql. Running it once a minute, works great so far.

Categories