SimpleXML parse Child of a Child - php

I am retrieving some similar XML from the Yahoo API -
<ResultSet version="1.0">
<Error>0</Error>
<ErrorMessage>No error</ErrorMessage>
<Locale>us_US</Locale>
<Quality>99</Quality>
<Found>1</Found>
<Result>
<quality>99</quality>
<latitude>51.501690</latitude>
<longitude>-0.125442</longitude>
<offsetlat>51.501690</offsetlat>
<offsetlon>-0.125442</offsetlon>
<radius>500</radius>
<name>51.501690392606974, -0.1254415512084961</name>
<woeid>26352062</woeid>
</Result>
</ResultSet>
How would I go about accessing the child woeid for example?
I can access quality, longitude etc but I am a little unsure as to how to access a child of a child - is this even the correct terminology?
Any help appreciated.
Thanks

<?php
$xml = simplexml_load_file("XML.xml");
//echo woeid
echo $xml->Result->woeid;
?>
That's just an easy example of how to do it with the xml-file you provided.
You might also run into files where there's more than one <Result> child, in which case you can access them all like this:
<?php
$xml = simplexml_load_file("XML.xml");
//echo all woeid's
foreach($xml->Result as $result) {
echo $result->woeid;
}
?>

Related

SimpleXML parsing through namespace items with ->children

I am parsing through the following XML file:
testxml.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?><document>
<node id="n0">
<data key="d6">
<y:GenericNode configuration="TEXT I WANT TO GET">
<y:Geometry height="56.030557066666574" width="181.68810666666667" x="638.4599149206349" y="143.24969103333325"/>
<y:Fill color="#FFCC66" color2="#FF9900" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="34.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="181.68810666666667" x="0.0" y="10.882466033333287">Text I want to Get<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="-0.5" labelRatioY="0.0" nodeRatioX="-0.5" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
I am interested in only a handful of attributes, namely the node id, data key which I am able to get with the code below. However, when I move into the y: namespace I get nothing.
xmlparser.php
<?php
$xml = simplexml_load_file("testxml.xml")
or die("Error: Cannot create object - check that the XML file exists and is
not corrupted"); print_r($xml);
echo $xml->node[0]['id']; // This works
echo $xml->node[0]->data[0]['key']; // This works
echo $xml->children('y', true)->GenericNode->attributes()->configuration; // Nothing
echo $xml->children('y', true)->GenericNode->NodeLabel; // Nothing
?>
I've read through previous answers on similar issues, based on which I adopted the children approach. However I can't get this to work, and I have no idea how to implement some of the other approaches such as declaring namespaces and the xpath approach.
Any help would be greatly appreciated.
That's because y:GenericNode isn't direct child of the root element, so you shouldn't be accessing it directly from $xml :
$xml->node->data->children('y', true)->GenericNode->attributes()->configuration;
quick test : https://eval.in/761412

Parse XML to HTML with PHP SimpleXMLElement

I am having some issues with SimpleXMLElement that I was hoping to get some help.
I was reading about SimpleXMLElement and I built a PHP page to parse this XML:
<?xml version='1.0'?>
<AdXML>
<Response>
<Campaign>
<Overview>
<Name>strip</Name>
<Description>category</Description>
<Status>L</Status>
</Overview>
<Pages>
<Url>page01</Url>
<Url>page02</Url>
<Url>page03</Url>
</Pages>
</Campaign>
</Response>
</AdXML>
Tag "Pages" can have any number of tags "Url" other tags might have only one value, like the tag "Name" for example.
Reading about SimpleXMLElement I ended up with the following code:
$xmlparsed = new SimpleXMLElement($xml); //my xml is being sent as variable
To display single values I am using the code below without a problem:
<?php echo $xmlparsed->Response[0]->Campaign[0]->Overview[0]->Name;?>
Everything works fine. But when I try to parse a tag with multiple lines I get only one line, and everytime I refresh the page it gives me a different "url" value. This is the code I am using:
<?php foreach ($xmlparsed->Response->Campaign->Pages as $Pages) {echo $Pages->Url, PHP_EOL;} ?>
According to PHP's site: http://php.net/manual/en/simplexml.examples-basic.php this should work, but it isn't.
Since I am not expert on PHP I am testing code on a trial-and-error basis.
What am I doing wrong here?
thanks in advance for any help.
You only have one Pages so you are only entering that foreach once. Try looping on the urls.
$xml = "<?xml version='1.0'?>
<AdXML>
<Response>
<Campaign>
<Overview>
<Name>strip</Name>
<Description>category</Description>
<Status>L</Status>
</Overview>
<Pages>
<Url>page01</Url>
<Url>page02</Url>
<Url>page03</Url>
</Pages>
</Campaign>
</Response>
</AdXML>";
$xmlparsed = new SimpleXMLElement($xml);
foreach ($xmlparsed->Response->Campaign->Pages->Url as $url) {
echo $url, PHP_EOL;
}
Output:
page01
page02
page03
You can also use XPath.
foreach( $xml->xpath( 'Response/Campaign/Pages/Url' ) as $url ) {
echo $url;
}

Trouble figuring out how parsed xml is stored - simpleXML

Let's say my XML is like this:
<?xml version="1.0"?>
<lists>
<list
path=".">
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
.
.
.
</list>
</lists>
And I store it in a SimpleXML object using
$xml_list = simplexml_load_file(dirname(__FILE__).'/svn_list.xml');
How would I access for example, the revision variable containing 1558?
I can't seem to figure it out using a combination of echo and print_r.
SimpleXML uses a set of classes which implement iterators to work through them, so you can loop through each node using foreach, however the easiest way to navigate the XML once it's loaded is by using SimpleXMLElement::xPath(). To get revision 1558, you can make the following call:
$commit = $xml_list->xpath('//list/entry/commit[#revision="1558"]');
This will return you the nodes underneath <commit revision="1558">, and you can then access them from the $commit variable, which extends ArrayObject.
To get the actual content of the <author> element, you must do the following:
print((string)$commit[0]->author);
SimpleXMLElement instances need to be cast to a type to expose their actual values.
Also, if you want to dump the content of $commit to see its child nodes, the easiest way is to call the asXml() method as follows:
print($commit[0]->asXml());
You are facing difficulties because you have error on your XML file , The </entry> tag was not closed.
You could traverse like this.
<?php
$xml='<lists>
<list>
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
</entry>
</list>
</lists>';
$xml = simplexml_load_string($xml);
foreach ($xml->list->entry[0]->commit->attributes() as $a=>$v)
{
echo $v;
}
OUTPUT :
1668

Adding Nodes to Existing XML

The problem i was having is the Root XML was being produced every time it writes to the XML.
The Main issue was setting up Child and Defining the Root. From the help of Łza
I now understand the Root XML Node is ignored.
So then you setup and create a Child and then add your content, And example of the correct format is.
$xml = simplexml_load_file('FILENAME.xml'); // Load XML File Need to add IF Statment to create if does not exist
$result = $xml->addchild('Result'); // Ignore Root NODE and Add Child Results
$result->addChild('Time', gmdate('D-M-Y -H:i:s')); // Rest of the below adds Child to Result and outputs results
$result->addChild('Channel', $Site);
$result->addChild('Type', '**');
$result->addChild('Process', $Status);
$result->addChild('SKU', $code->SKU);
$result->addChild('item', $item);
$result->addChild('Status', '$Feedback');
$result->addChild('ErrorID', '$Error');
$result->addChild('Message', '$Message');
$xml->asXml('FILENAME.xml'); //Write to file would be
// All of the above Code is using variables from another part of the script
The output would be
<Root>
<Result>
<Time>Fri-May-2013 -09:15:22</Time>
<Channel>20</Channel>
<Type>**</Type>
<Process>Update</Process>
<SKU>98746524765</SKU>
<Item/>
<Status>Problem</Status>
<ErrorID>999-Error</ErrorID>
<Message>Unknown file format support</Message>
</Result>
<Result>
<Time>Fri-May-2013 -09:15:22</Time>
<Channel>20</Channel>
<Type>**</Type>
<Process>Update</Process>
<SKU>5412254785</SKU>
<Item/>
<Status>Problem</Status>
<ErrorID>123-Error</ErrorID>
<Message>Invalid Item</Message>
</Result>
</Root>
Thanks
Try to use SimpleXMLElement library instead hardcoded xml creation. This is maybe more complicate to use at the begining, but much more safe (I mean avoid possible errors in xml structure when you hardcode the xml) and easy to use when you just get start to use it.
And easy to add/remove nodes, childnodes.
This is an example for your code:
$xml = new SimpleXMLElement('<xml/>');
$data = $xml->addChild('data');
$result = $data->addChild('Result');
$result->addChild('Time', gmdate('D-M-Y -H:i:s'));
$result->addChild('Channel', $SiteID);
// ... and the same way create all your xml nodes.
// if you want add next <result> node witch all elements repeat the code, (or put it in loop if you want more <result> elements):
$result = $data->addChild('Result');
$result->addChild('Time', gmdate('D-M-Y -H:i:s'));
$result->addChild('Channel', $SiteID);
// and after create all nodes save the file:
$xml->asXml('DHError.xml');
above code will create xml:
<xml>
<data>
<Result>
<Time>Fri-May-2013 -12:14:39</Time>
<Channel>data</Channel>
</Result>
<Result>
<Time>Fri-May-2013 -12:14:39</Time>
<Channel>data</Channel>
</Result>
</data>
</xml>
Thats it. Then if you need to load and process the xml it would be easy:
To load the File simply use:
$xml2 = simplexml_load_file('DHError.xml');
// to add new node <Result>:
$resultNext = $xml2->data->addchild('Result');
$resultNext->addChild('Time', gmdate('D-M-Y -H:i:s'));
$resultNext->addChild('Channel', $SiteID);
//and save file
$xml2->asXml('DHError.xml');
this create a xml:
<?xml version="1.0" ?>
<xml>
<data>
<Result>
<Time>Fri-May-2013 -12:27:24</Time>
<Channel>data</Channel>
</Result>
<Result>
<Time>Fri-May-2013 -12:27:24</Time>
<Channel>data</Channel>
</Result>
<Result>
<Time>Fri-May-2013 -12:27:24</Time>
<Channel>data</Channel>
</Result>
</data>
</xml>

How to parse a specific xml file using PHP simpleXML

I know there is already a lot of topics about simpleXML and PHP, but I need help with an specific xml code.
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
I need a foreach to get the data from each "product" like this:
<?
$feedUrl = 'url to xml file';
$rawFeed = file_get_contents($feedUrl);
$xml = simplexml_load_string($rawFeed);
foreach ($item ...????? ?)
{
}
How can I do this foreach to get the data. I tried all that I know without success.
Thanks.
First, you need <?xml version="1.0" encoding="UTF-8"?> as the first line in your XML, otherwise it's not valid. Then, and this will help you debug all sorts of things over your coding career, try this line:
echo "<pre>".print_r($xml,true)."</pre>";
That will give you the exact layout of the object you get back from the simplexml_load_string() call. From there, since you have a visual of the object layout, you should be able to figure out how to parse it. Incidentally, in your case, I think you'd need to do something like:
foreach($xml->vitrine as $element) {
// your code goes here
}
It seems PHP gets rid of evrything after the whitespace, because product id was changed to just product. Anyway here's the code.
<?php
$v = <<<ABC
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
ABC;
$xml = simplexml_load_string($v);
//print_r($xml);
foreach ($xml->product as $c){
echo $c->loja; //echoing out value of 'loja'
}
Outputs
ApetreXo.com
Fast Shop.com.b...

Categories