PHP access XML node element - php

I am trying to edit some XML with PHP. Currently the XML looking something like:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Main Title</title>
<link>http://exmaple.com</link>
<description> blahblahblah </description>
<language>en</language>
<item>
<title>Tite1</title>
<link>http://www.example.com (THIS IS WHAT I WANT)</link>
<description>blah blah blah</description>
</item>
.
.
.
</channel>
</rss>
I've tried to access the 2nd level link but my code only changes the first Link node value. Here is the code:
$xml->load('http://www.google.com/doodles/doodles.xml');
$element = $xml->getElementsByTagName('channel')->item(0);
$secondlvl = $element->getElementsByTagName('item')->item(0);
$2ndlevellinknode = $element->getElementsByTagName('link')->item(0);
$2ndlevellinknode->nodeValue = $newvalue;
Any suggestions? Also is it possible to use this line of code in a for loop like this
for ($i = 0; $i <= 20; $i++) {
$element = $xml->getElementsByTagName('channel')->item(0);
$secondlvl = $element->getElementsByTagName('item')->item(0);
$2ndlevellinknode = $element->getElementsByTagName('link')->item($i);
$2ndlevellinknode->nodeValue = $newvalue;
}

this should give you an idea.
$f = simplexml_load_file('test.xml');
print $f->channel->title . "\n";
print $f->channel->link . "\n";
print $f->channel->description . "\n";
foreach($f->channel->item as $item) {
print $item->title . "\n";
}

Related

Getting XML file from another domain to Mysql database

I'm trying to get xml information from an url to be imported into mysql trough a php script, but I'm having some trouble and my experience dosen't cover this area.
The XML is formed as this example:
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:g="http://base.google.se/ns/1.0">
<channel>
<title></title>
<description></description>
<link></link>
<item>
<g:id></g:id>
<title></title>
<g:product></g:product>
</item>
<item>
<g:id></g:id>
<title></title>
<g:product></g:product>
</item>
and so on...
with the php script:
<?php
include '../connection-to-db.php';
$str_xml = file_get_contents('http://www.example.com/xmls/xmlfile.xml');
$library = new SimpleXMLElement($str_xml);
$arr = json_decode( json_encode($library) , true);
var_dump ($arr);
echo "Array got " .sizeof($arr['item']) . " items.<br> <br>";
if (sizeof($arr['item']) > 155555500) {
mysql_query("TRUNCATE TABLE google_stat");
$count = 0;
foreach ($arr['item'] as $shelf)
{
$gId = mysql_real_escape_string($shelf['g:id']);
$Title = mysql_real_escape_string($shelf['title']);
$gProductType = mysql_real_escape_string($shelf['g:product']);
mysql_query("INSERT INTO google_stat (gid, title, gcategory)
VALUES ('$gID', '$Title', '$gCategory')")
or die(mysql_error());
$count ++;
}
echo " Counted: " . $count . "inserts";
} else {
echo "Non counted, no insert done";
}
?>
Problem is when SimpleXMLElement it seems all items with g: in there names disappears when I look at the output, it dosen't even fint any items.
I've even tried with a localfile with same XML tree and can't even make that work.
I'm thankful for any help given, since I realize more and more I'm on deep water with this.
UPDATE:
<?php
include '../connection-to-db.php';
$str_xml = file_get_contents('http://www.example.com/xmls/xmlfile.xml');
$library = new SimpleXMLElement($str_xml);
$arr = json_decode( json_encode($library) , true);
echo "Array got " .sizeof($library->channel->item) . " items.<br> <br>";
if (sizeof($library->channel->item) > 100) {
mysql_query("TRUNCATE TABLE google_stat");
$count = 0;
foreach ($library->channel->item as $shelf)
{
$gId = (string) $shelf->children('g', TRUE)->id;
$Title = (string) $shelf->title;
$gProductType = $shelf->children('g', TRUE)->product;
echo $gId."<br />";
echo $Title."<br />";
echo $gProductType."<br />";
$count ++;
}
echo " Counted: " . $count . "inserts";
} else {
echo "Non counted, no insert done";
}
?>
Now I get the number of items in array, but $gId, $Title etc, dosen't echo any values.
Edit2: had to high array check, it works.
It has to do with the namespace prefix you want. You can access the g: items like so:
<?php
$str_xml = file_get_contents('test.xml');
$library = new SimpleXMLElement($str_xml);
$count = 0;
foreach ($library->channel->item as $shelf)
{
$gId = (string) $shelf->title;
$Title = (string) $shelf->children('g', TRUE)->id;
$gProductType = (string) $shelf->children('g', TRUE)->product;
echo $gId."<br />";
echo $Title."<br />";
echo $gProductType."<br />";
$count ++;
}
echo " Counted: " . $count . " inserts";
?>
See https://www.sitepoint.com/simplexml-and-namespaces/ for further reference.
xml.test
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:g="http://base.google.se/ns/1.0">
<channel>
<title>product</title>
<description>lots of products</description>
<link>www.example.com</link>
<item>
<g:id>ID 1</g:id>
<title>Title 1</title>
<g:product>Product 1</g:product>
</item>
<item>
<g:id>ID 2</g:id>
<title>Title 2</title>
<g:product>Product 2</g:product>
</item>
</channel>
</rss>
Output:
Title 1
ID 1
Product 1
Title 2
ID 2
Product 2
Counted: 2 inserts

Same variable from multiple XML

$var1 = new SimpleXMLElement('CSVXML/xvar.xml', null, true);
$var2 = new SimpleXMLElement('CSVXML/yvar.xml', null, true);
let's say I get variables from two diffrents XML files, in the first XML files
<Number>3698</Number>
<InternalNumber>1</InternalNumber>
<Name>Bob</Name>
<Number>3500</Number>
<InternalNumber>2</InternalNumber>
<Name>Mike</Name>
<Number>2775</Number>
<InternalNumber>3</InternalNumber>
<Name>Dan</Name>
in the second XML I get the followings
<player>3698</player>
<group>A</group>
I do this
$varID = $var1->Number;
$varnumber = $var2->player;
if ($varID == $varnumber ){
echo '$var1->InternalNumber';
}
is this possible ?
I simply want to put out a variable, is A for XML! = B from XML2, is there anyway possible to do that?
I found this working fine. tested link
<?php
$str = <<<XML
<items>
<item>
<Number>3698</Number>
<InternalNumber>1</InternalNumber>
<Name>Bob</Name>
</item>
<item>
<Number>3500</Number>
<InternalNumber>2</InternalNumber >
<Name>Mike</Name>
</item>
<item>
<Number>2775</Number>
<InternalNumber>3</InternalNumber>
<Name>Dan</Name>
</item>
</items>
XML;
$str2 = <<<XML
<item>
<player>3698</player>
<group>A</group>
</item>
XML;
$da = new SimpleXMLElement($str2);
$varnumber = $da->player;
$data = new SimpleXMLElement($str);
foreach ($data->item as $item)
{
$this_number = $item->Number;
//echo $this_number."-".$item->InternalNumber."-".$varnumber."\n";
if((int)$this_number == (int)$varnumber ){
$this_internalnumber = $item->InternalNumber;
echo $this_internalnumber."\n";
}
else{
echo "No Match found \n";
}
}
Hope this helps.

how can i load a xml, and save it with php?

hey guys I'm trying to parse a xml(feeds) and save it with php?(I'm halfway),.i already achieve to load the xml and display just the data i need to display,.now how can i save the xml?
this is my code :
<?php
$html = "";
$url = "http://www.conciencia.net/rss.aspx";
$xml = simplexml_load_file($url);
$channel_title = $xml->channel->title;
$channel_link = $xml->channel->link;
$managingEditor = $xml->channel->managingEditor;
$channel_description = $xml->channel->description;
$lbd = $xml->channel->lastBuildDate;
$html .= "<br/>$channel_title";
$html .= "<br/>$channel_link";
$html .= "<br/>$managingEditor";
$html .= "<br/>$lbd";
$html .= "<br/>$channel_description<br/>";
for($i = 0; $i < 7; $i++){
$pubDate = $xml->channel->item[$i]->pubDate;
$title = $xml->channel->item[$i]->title;
$link = $xml->channel->item[$i]->link;
$guid = $xml->channel->item[$i]->guid;
$author = $xml->channel->item[$i]->author;
$description = $xml->channel->item[$i]->description;
$url0 = $xml->channel->item[$i]->enclosure->attributes()->url;
for($ii = 0; $ii < 2; $ii++){
$url = $xml->channel->item[$i]->enclosure[$ii]->attributes()->url;
}
$html .= "<br/>$pubDate";
$html .= "<a href='$link'><h3>$title</h3></a>";
$html .= "<br/>$guid";
$html .= "<br/>$author";
$html .= "<br/>$description";
$html .= "<br/>$url0";
$html .= "<br/>$url";
$html .= "<br/>$link<br/>";
}
echo $html;
?>
that code is working good, loading the tags from the xml i just want to display,
what i want to do after that is create a xml(as is below structured) and save the data.
how can i achieve that ?
myxml.xml
<channel>
<title>$channel_title</title>
<link>$channel_link</link>
<managingEditor>$managingEditor</managingEditor>
<channel_description>$channel_description</channel_description>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
<item>
<title>$title</title>
<guid>$guid</guid>
<author>$author</author>
<description>$description</description>
<enclosure0>$url0</enclosure0>
<enclosure1>$url</enclosure>
</item>
</channel>
Well you can simly use normal string concatenation to write the xml file(alternatively you could spend time doing it the hard way with an xml object, which some might consider more proper).
Next you open a file with fopen() in write mode. if the file doesn't exist, it will be created. make sure you have permission to write to that directory, or the file will not be written(and if error reporting is strict, a fatal error will be thrown, else just a warning). second, you use fwrite() to write to the file.for more information, read the manual on filesystem functions
$file = '/path/to/mynewxmlfile.xml';
$data =
'
<?xml version="1.0"?>
<channel>
<title>'.$channel_title.'</title>
<link>'.$channel_link.'</link>
<managingEditor>'.'$managingEditor.</managingEditor>
<channel_description>'.$channel_description.'</channel_description>
';
for($i = 0; $i < 7; $i++){
$pubDate = $xml->channel->item[$i]->pubDate;
$title = $xml->channel->item[$i]->title;
$link = $xml->channel->item[$i]->link;
$guid = $xml->channel->item[$i]->guid;
$author = $xml->channel->item[$i]->author;
$description = $xml->channel->item[$i]->description;
$url0 = $xml->channel->item[$i]->enclosure->attributes()->url;
for($ii = 0; $ii < 2; $ii++){
$url = $xml->channel->item[$i]->enclosure[$ii]->attributes()->url;
}
$data .=
'
<item>
<title>'.$title.'</title>
<guid>'.$guid.'</guid>
<author>'.$author.'</author>
<description>'.$description.'</description>
<enclosure0>'.$url0.'</enclosure0>
<enclosure1>'.$url.'</enclosure1>
</item>
';
}
$data .= '</channel>';
fwrite(fopen($file,'w'),$data);
Alternatively, you could use simplexml_load_string() to load the string as xml, then use asXml() to write it to disk, like so:
$data = simplexml_load_string($data);
$data->asXml($file);
Read the docs http://php.net/manual/en/simplexmlelement.asxml.php
$xml->asXml('rss.xml');
Edit
and if you want to create a new xml there is an answer https://stackoverflow.com/a/143192/1742977

Get value form SimpleXMLIterator if has no children

Please check this code, taken from here
<?php
$xml = <<<XML
<books>
<book>
<title>PHP Basics</title>
<author>Jim Smith</author>
</book>
<book>XML basics</book>
</books>
XML;
$xmlIterator = new SimpleXMLIterator($xml);
for( $xmlIterator->rewind(); $xmlIterator->valid(); $xmlIterator->next() ) {
foreach($xmlIterator->getChildren() as $name => $data) {
echo "The $name is '$data' from the class " . get_class($data) . "\n";
}
}
?>
How to get values from all book nodes additional "XML basics" (in second book node) using iterator?
This will give you XML basics as output.
<?php
$xml = <<<XML
<books>
<book>
<title>PHP Basics</title>
<author>Jim Smith</author>
</book>
<book>XML basics</book>
</books>
XML;
for( $xmlIterator->rewind(); $xmlIterator->valid(); $xmlIterator->next() ) {
$xmlIterator->next();
echo $xmlIterator->getChildren();
}
?>
[:edit]
it will display both of books
$xmlIterator = new SimpleXMLIterator($xml);
for( $xmlIterator->rewind(); $xmlIterator->valid(); $xmlIterator->next() ) {
foreach($xmlIterator->getChildren() as $name => $data) {
echo "$data<br />";
break;
}
echo $xmlIterator->getChildren();
}

Trying to extract simplexml attribute

I have an XML file that looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<product sku="CATDJ" type="CAT" vendor="DJ" active="1" on_sale="0" discountable="0">
<name>CATALOGS</name>
<short_description><![CDATA[The DJ catalog features 182 pages]]></short_description>
<long_description><![CDATA[The DJ catalog features 182 pages.]]></long_description>
<price>1.5</price>
<stock_quantity>65</stock_quantity>
<release_date>2003-05-06T00:00:00-04:00</release_date>
<barcode>782421791315</barcode>
</product>
....
I can get the price, stock_quatity, and barcode, but not the sku, active or discountable data.
This is what my code looks like this:
$myinv = simplexml_load_file('http://www.*******.com/products.xml');
foreach ($myinv as $invinfo):
$sku = $invinfo->products->product->sku;
$active = $invinfo->products->product->active;
$deductible = $invinfo->products->product->discountable;
$qty=$invinfo->stock_quantity;
$price=$invinfo->price;
$upc=$invinfo->barcode;
What Am I doing wrong? BTW, I'm new to php.
Thank you for your help.
I always typecast everything I get from SimpleXML, because it always returns a SimpleXMLElement. var_dump your variables to see for yourself.
<?php
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<product sku="CATDJ" type="CAT" vendor="DJ" active="1" on_sale="0" discountable="0">
<name>CATALOGS</name>
<short_description><![CDATA[The DJ catalog features 182 pages]]></short_description>
<long_description><![CDATA[The DJ catalog features 182 pages.]]></long_description>
<price>1.5</price>
<stock_quantity>65</stock_quantity>
<release_date>2003-05-06T00:00:00-04:00</release_date>
<barcode>782421791315</barcode>
</product>
</products>';
$myinv = new SimpleXMLElement($xml);
$products = $myinv->product;
foreach ($products as $product){
$attrs = $product->attributes();
$sku = $attrs->sku;
$active = $attrs->active;
$discountable = $attrs->discountable;
$qty = $product->stock_quantity;
$price = $product->price;
$upc = $product->barcode;
echo (string)$sku . "<br>\n";
echo (string)$active . "<br>\n";
echo (string)$discountable . "<br>\n";
echo (string)$qty . "<br>\n";
echo (string)$price . "<br>\n";
echo (string)$upc . "<br>\n";
}
?>
XPath can do the job of getting the value of an attribute with $xpath->query("//product[#name='sku']/#value");.

Categories