I am trying to parse XML with PHP. The XML is a response from ebay getsellerlist api, and is structured like so:
<!--?xml version="1.0" encoding="UTF-8"?-->
<getsellerlistresponse xmlns="urn:ebay:apis:eBLBaseComponents">
<timestamp>2016-08-11T14:17:39.869Z</timestamp>
<ack>Success</ack>
<version>967</version>
<build>E967_CORE_APISELLING_17965876_R1</build>
<itemarray>
<item>
<itemid>itemid1</itemid>
<listingdetails>
<viewitemurl>itemurl1</viewitemurl>
</listingdetails>
<primarycategory>
<categoryid>categoryid1</categoryid>
<categoryname>categoryname1</categoryname>
</primarycategory>
<title>title1</title>
<picturedetails>
<galleryurl>url1</galleryurl>
<photodisplay>thumbnail1</pictureurl>
<pictureurl>picture1</pictureurl>
</picturedetails>
</item>
</itemarray>
</getsellerlistresponse>
My php is as follows:
<?
$xml = '<!--?xml version="1.0" encoding="UTF-8"?--><getsellerlistresponse xmlns="urn:ebay:apis:eBLBaseComponents"><timestamp>2016-08-11T14:17:39.869Z</timestamp><ack>Success</ack><version>967</version><build>E967_CORE_APISELLING_17965876_R1</build><itemarray><item><itemid>itemid1</itemid><listingdetails><viewitemurl>itemurl1</viewitemurl></listingdetails><primarycategory><categoryid>categoryid1</categoryid><categoryname>categoryname1</categoryname></primarycategory><title>title1</title><picturedetails><galleryurl>url1</galleryurl><photodisplay>thumbnail1</pictureurl><pictureurl>picture1</pictureurl></picturedetails></item><item><itemid>itemid2</itemid><listingdetails><viewitemurl>itemurl2</viewitemurl></listingdetails><primarycategory><categoryid>categoryid2</categoryid><categoryname>categoryname2</categoryname></primarycategory><title>title1</title><picturedetails><galleryurl>url2</galleryurl><photodisplay>thumbnail2</pictureurl><pictureurl>picture2</pictureurl></picturedetails></item></itemarray></getsellerlistresponse>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$title_nodes = $dom->getElementsByTagName('title');
$titles = array();
foreach ($title_nodes as $node) {
$titles[] = $node->nodeValue;
echo $node->nodeValue;
}
echo $titles[0];
echo count($titles);
?>
When I run it, I get a blank page, no errors, nothing.
If I check $titles length using count(), it comes back as zero.
For some reason it is not getting the title node (or any other nodes) and I can't figure out how to parse the xml string with php and get the node values.
Any help most appreciated, if the question is vague or lacking detail, please let me know and I will correct it.
The XML isn't valid:
Unable to parse any XML input. org.jdom2.input.JDOMParseException: Error on line 2: The element type "photodisplay" must be terminated by the matching end-tag "".
And that's only after you remove the comments in your XML declaration:
<!--?xml version="1.0" encoding="UTF-8"?-->
shoud be
<?xml version="1.0" encoding="UTF-8"?>
Working demo:
<?php
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<getsellerlistresponse xmlns="urn:ebay:apis:eBLBaseComponents">
<timestamp>2016-08-11T14:17:39.869Z</timestamp>
<ack>Success</ack>
<version>967</version>
<build>E967_CORE_APISELLING_17965876_R1</build>
<itemarray>
<item>
<itemid>itemid1</itemid>
<listingdetails>
<viewitemurl>itemurl1</viewitemurl>
</listingdetails>
<primarycategory>
<categoryid>categoryid1</categoryid>
<categoryname>categoryname1</categoryname>
</primarycategory>
<title>title1</title>
<picturedetails>
<galleryurl>url1</galleryurl>
<photodisplay>thumbnail1</photodisplay>
<pictureurl>picture1</pictureurl>
</picturedetails>
</item>
</itemarray>
</getsellerlistresponse>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$title_nodes = $dom->getElementsByTagName('title');
$titles = array();
foreach ($title_nodes as $node) {
$titles[] = $node->nodeValue;
echo $node->nodeValue;
}
echo $titles[0];
echo count($titles);
Related
I'm trying to parse a request sent by ThunderBird to my CalDAV Server and from an example taken from stackoverflow with an XML like :
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<last_updated>2009-11-30 13:52:40</last_updated>
<product>
<element_1>foo</element_1>
<element_2>foo</element_2>
<element_3>foo</element_3>
<element_4>foo</element_4>
</product>
</products>
Using the function :
$XMLr = new XMLReader;
$XMLr->open('test.xml');
$doc = new DOMDocument;
// move to the first <product /> node
while ($XMLr->read() && $XMLr->name !== 'product');
// now that we're at the right depth, hop to the next <product/> until the end of the tree
$node = simplexml_import_dom($doc->importNode($XMLr->expand(), true));
// now you can use $node without going insane about parsing
$children = $node->children();
foreach($children as $child)
{
echo $child->getName();
echo "\n";
}
I get the answer "element_1 element_2 element_3 element_4 ", but if I use the same function on my request :
<?xml version="1.0" encoding="UTF-8"?>
<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/" xmlns:C="urn:ietf:params:xml:ns:caldav">
<D:prop>
<D:resourcetype/>
<D:owner/>
<D:current-user-principal/>
<D:supported-report-set/>
<C:supported-calendar-component-set/>
<CS:getctag/>
</D:prop>
</D:propfind>
Replacing $XMLr->name !== 'product' by $XMLr->name !== 'D:prop' I get a white screen...
What do I do wrong ?
How can I get the answer "ressourcetype owner current-user-principal etc ..." ?
I try with XMLReader and simplexml_import_dom without success but in opposite, with DomDocument you can do it:
// Just for display test results
$break_line = '<br>';
if (php_sapi_name() === 'cli') {
$break_line = "\n";
}
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/" xmlns:C="urn:ietf:params:xml:ns:caldav">
<D:prop>
<D:resourcetype/>
<D:owner/>
<D:current-user-principal/>
<D:supported-report-set/>
<C:supported-calendar-component-set/>
<CS:getctag/>
</D:prop>
</D:propfind>';
$xml_document = new DomDocument(); // http://fr2.php.net/manual/fr/class.domdocument.php
$xml_document->loadXML($xml); // Or load file with $xml_document->load('test.xml);
$elements = $xml_document->getElementsByTagName('prop');
// $elements is a DOMNodeList object: http://fr2.php.net/manual/fr/class.domnodelist.php
foreach($elements as $element) {
// $element is a DOMElement object: http://fr2.php.net/manual/fr/class.domelement.php
$childs = $element->childNodes;
// $childs is DOMNodeList
foreach ($childs as $child) {
// $element is a DOMElement object
if ($child instanceof DOMElement) {
echo $child->nodeName . $break_line;
}
}
}
White screen normally means error.
Put error_reporting on E_ALL
error_reporting('E_ALL');
Following is my XML file i want to update the doller and cent values which are inside latestBid. I first tried the doller values but it's not working. i even tried to update the description ('//item[id="4"]/description') even that didn't work. Please tell me what i'm doing wrong here.
XML file
<?xml version="1.0"?>
<items>
<item>
<itemNumber>4</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>2342</doller>
<cent>23</cent>
</bidPrice>
</latestBid>
</item>
<item>
<itemNumber>5</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>35345</doller>
<cent>78</cent>
</bidPrice>
</latestBid>
</item>
</items>
PHP file
<?php
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 45;
$bidCent=55;
$doc = new DomDocument();
$xml=simplexml_load_file($url);
//echo "came 1";working
foreach ($xml->xpath('//item[#itemNumber="4"]/latestBid/bidPrice/doller') as $desc) {
echo "came 2";//nt working
$dom=dom_import_simplexml($desc);
$dom->nodeValue = $bidDoller;
}
file_put_contents($url, $xml->asXML());
?>
edited. Still not working
thank you every one for the support by editing and answering I finally did it. since it wasn't easy for me to do this i'm posting the answer to help someone like me :).
i didn't change the xml.
php file
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 85;
$bidCent=95;
$xml=simplexml_load_file($url);
$resultDoller= $xml->xpath('//item[itemNumber="'.$itemNumber.'"]/latestBid/bidPrice/doller');
$resultCent= $xml->xpath('//item[itemNumber="'.$itemNumber.'"]/latestBid/bidPrice/cent');
$resultDoller[0][0]=$bidDoller;
$resultCent[0][0]=$bidCent;
print $xml->asXML();
file_put_contents($url, $xml->asXML());
Following worked for me,
//XML
<?xml version="1.0"?>
<items>
<item id="4">
<itemNumber>4</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>2342</doller>
<cent>23</cent>
</bidPrice>
</latestBid>
</item>
<item>
<itemNumber>5</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>35345</doller>
<cent>78</cent>
</bidPrice>
</latestBid>
</item>
</items>
//PHP
<?php
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 45;
$bidCent=55;
$doc = new DomDocument();
$xml=simplexml_load_file($url);
$result = $xml->xpath('//item[#id="4"]/latestBid/bidPrice/doller');
echo "<pre>";
print_r($result);
//echo "came 1";working
foreach ($xml->xpath('//item[#id="4"]/latestBid') as $desc) {
echo "came 2";//nt working
$dom=dom_import_simplexml($desc);
$dom->nodeValue = $bidDoller;
}
//file_put_contents($url, $xml->asXML());
?>
I have a small requirement where I need to create a XML file on the fly. It was no problem for me to create a normal xml file which would be looking like this:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name></name>
</item>
</root>
But my requirement is such that I need to create a XML file whose output is:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name url = "C:\htdocs\proj1\source_file1"/>
<name url = "C:\htdocs\proj1\source_file2"/>
<name url = "C:\htdocs\proj1\source_file3"/>
</item>
</root>
I have tried in this fashion:
<?php
$domtree = new DOMDocument('1.0', 'UTF-8');
$domtree->formatOutput = true;
$xmlRoot = $domtree->createElement("root");
$xmlRoot = $domtree->appendChild($xmlRoot);
$item = $domtree->createElement("item");
$item = $xmlRoot->appendChild($item);
$name= $domtree->createElement("name");
$name = $item->appendChild($name);
$sav_xml = $domtree->saveXML();
$handle = fopen("new.xml", "w");
fwrite($handle, $sav_xml);
fclose($handle);
?>
But I wanted to append/add the url="path" to my elements. I have tried declaring variables with url and path but this throws me errors like:
Uncaught exception 'DOMException' with message 'Invalid Character Error'
Any ideas how to approach this problem!
Thanks
You just have to declare that attributes via php DOM:
...
$name= $domtree->createElement("name");
$urlAttribute = $domtree->createAttribute('url');
$urlAttribute->value = 'C:\htdocs\proj1\source_file1';
$name->appendChild($urlAttribute);
$item->appendChild($name);
...
Link to DOMDocument docs
Ive been trying every way possible to create cdata entries in my xml. My latest attempt is as follows. I can't even get passed for the first statement where im creating a new DOMDocument. Any ideas?
<?php
$xml = '
<?xml version="1.0" encoding="ISO-8859-1"?>
<cars>
<make name="Ford">
<model>Mustang</model>
</make>
<make name="Honda">
<model>Accord</model>
</make>
</cars>
';
$dom = new DOMDocument;
$dom->loadXML($xml);
$xml = simplexml_import_dom($dom);
print "working";
?>
You should not have any characters before the XML declaration. Remove the line break at $xml = '.
The neatest solution would be to use heredoc syntax:
$xml = <<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<cars>
<make name="Ford">
<model>Mustang</model>
</make>
<make name="Honda">
<model>Accord</model>
</make>
</cars>
XML;
Have a look at: DOMDocument::createCDATASection
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>
<cars>
<make name="Ford">
<model>Mustang</model>
</make>
<make name="Honda">
<model>Accord</model>
</make>
</cars>
';
$dom = new DOMDocument;
$dom->loadXML($xml);
$cdataNode = $dom->createCDATASection('<&>');
$dom->documentElement->appendChild($cdataNode);
echo $dom->saveXml();
Output:
<?xml version="1.0" encoding="ISO-8859-1"?>
<cars>
<make name="Ford">
<model>Mustang</model>
</make>
<make name="Honda">
<model>Accord</model>
</make>
<![CDATA[<&>]]></cars>
i haven't really worked with xml files before, but now i'm trying to get an xml file into a php array or object.
the xml file looks like this: (it's for translating a web app)
<?xml version="1.0" ?>
<content language="de">
<string name="login">Login</string>
<string name="username">Benutzername</string>
<string name="password">Passwort</string>
</content>
i tried the following:
$xml = new SimpleXMLElement("de.xml", 0, 1);
print_r($xml);
unfortunately, the values of the 'name' attribute are for some reason not in the php object. i'm looking for a way that allows me to retrieve the xml values by the name attribute.
for instance:
$xml['username'] //returns "Benutzername"
how can this be done?
appreciate your help :) cheers!
This one should explain the function to you:
<?php
$xml = simplexml_load_file('de.xml');
foreach($xml->string as $string) {
echo 'attributes: '. $string->attributes() .'<br />';
}
?>
The attributes() method from SimpleXMLElement class will help you - http://de.php.net/manual/en/simplexmlelement.attributes.php
$xmlStr = <<<XML
<?xml version="1.0" ?>
<content language="de">
<string name="login">Login</string>
<string name="username">Benutzername</string>
<string name="password">Passwort</string>
</content>
XML;
$doc = new DomDocument();
$doc->loadXML($xmlStr);
$strings = $doc->getElementsByTagName('string');
foreach ($strings as $node) {
echo $node->getAttribute('name') . ' = ' . $node->nodeValue . PHP_EOL;
}
You can use an xpath expression to get the element with the name you are looking for:
(string)current($xml->xpath('/content/string[#name="username"]'))