SimpleXML foreach doesn't work - php

I have following XML (source.xml):
<SHOP>
<SHOPITEM>
<ITEM_ID>3664</ITEM_ID>
<PRODUCT>Product n.1</PRODUCT>
<PRODUCT_NAME>Product n.1</PRODUCT_NAME>
<VARIANT_NAME/>
<MANUFACTURER>Jeffrey</MANUFACTURER>
<CODE>ABC123</CODE>
<EAN>123456789</EAN>
<DESCRIPTION>
Maybe later...
</DESCRIPTION>
<DESCRIPTION_HTML/>
<CATEGORIES>
<CATEGORY id="1" parent_id="0">ABx</CATEGORY>
</CATEGORIES>
</SHOPITEM>
<SHOPITEM>
...etc
And following code:
$xml = simplexml_load_file("source.xml", NULL, LIBXML_NOCDATA);
foreach ($xml->shopitem as $shopitem) {
echo $shopitem->item_id;
}
Unfortunately, it doesn't work. Even if I put echo 'a'; into foreach cycle, nothing appears. XML is valid. Tried var_dump($xml) and the XML looks to be loaded correctly. What is wrong? Thank you.

$xml = simplexml_load_file("source.xml", NULL, LIBXML_NOCDATA);
foreach ($xml->SHOPITEM as $shopitem) {
echo $shopitem->ITEM_ID;
}

Related

PHP updating xml CDATA fields with DOMdocument

I have the following XML data:
<?xml version="1.0" encoding="utf-8"?>
<source>
<publisher>some-data</publisher>
<publisherurl>some-data</publisherurl>
<lastBuildDate>a-date</lastBuildDate>
<element>
<sub-element><![CDATA[some-data]]></sub-element>
</element>
</source>
I'm trying to use PHP's built in DOMdocument parser to update the text inside sub-element.
I've tried:
$dom=new DOMDocument();
$dom->load("document.xml");
$ele=$root->getElementsByTagName('element');
foreach ($ele as $e) {
$e->getElementsByTagName('sub-element')->item(0)->nodeValue = "new val";
}
this kind of works but it removes the CDATA and just replaces it with new-val. I want to preserve the CDATA field so I tried the following:
$dom=new DOMDocument();
$dom->load("document.xml");
$ele=$root->getElementsByTagName('element');
foreach ($ele as $e) {
$sub=$e->getElementsByTagName('sub-element');
foreach($sub->childNodes as $child) {
if ($child->nodeType == XML_CDATA_SECTION_NODE) {
$child->nodeValue = 'new-val';
}
}
}
This seems like it should work but PHP returns the following Notice
Undefined property: DOMNodeList::$childNodes
Feel like I'm on the right path but I just can't figure out what I'm doing wrong here. Does anyone know how to fix?
My end goal output is:
<?xml version="1.0" encoding="utf-8"?>
<source>
<publisher>some-data</publisher>
<publisherurl>some-data</publisherurl>
<lastBuildDate>a-date</lastBuildDate>
<element>
<sub-element><![CDATA[new-val]]></sub-element>
</element>
</source>
You need to compare against firstChild
$xml = '<?xml version="1.0" encoding="utf-8"?>
<source>
<publisher>some-data</publisher>
<publisherurl>some-data</publisherurl>
<lastBuildDate>a-date</lastBuildDate>
<element>
<sub-element><![CDATA[some-data]]></sub-element>
</element>
<element>
<sub-element>some-other-data</sub-element>
</element>
</source>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$ele=$dom->getElementsByTagName('element');
foreach ($ele as $e) {
$item = $e->getElementsByTagName('sub-element')->item(0);
if($item->firstChild->nodeType == XML_CDATA_SECTION_NODE) { //<------
//it's CDATA do whatever
$item->firstChild->nodeValue = "new val";
} else {
//it's not , do something else
$item->nodeValue = "new val";
}
}
echo "<pre>";
print_r(htmlentities($dom->saveXML()));
echo "</pre>";
Output:
<?xml version="1.0" encoding="utf-8"?>
<source>
<publisher>some-data</publisher>
<publisherurl>some-data</publisherurl>
<lastBuildDate>a-date</lastBuildDate>
<element>
<sub-element><![CDATA[new val]]></sub-element>
</element>
<element>
<sub-element>new val</sub-element>
</element>
</source>
PS: if you don't have to make a distinction between CDATA or not, just use firstChild
foreach ($ele as $e) {
$item = $e->getElementsByTagName('sub-element')->item(0);
$item->firstChild->nodeValue = "new val";
}

Parsing xml response from ebay getsellerlist with php

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);

php SimpleXml and xpath: How to acces children inside node that have other namespace?

I am trying to loop through a set of records in an XML document, but cannot access subnodes that are in other namespaces.
this is my php code:
$xml = new SimpleXMLElement($xml);
$ns = $xml->getNamespaces(true);
$xml->registerXPathNamespace('ns', $ns['']);
$xmlRecords = $xml->xpath('//ns:recordData');
foreach ($xmlRecords as $record)
{
$enrichedData = $record->gzd->enrichedData; //Yes! Works!
$originalData = $record->gzd->originalData; //empty
}
The problem is that $orginalData remains empty, probably because al the subnodes inside node originalData belong to other namespaces. My question is: how do I get these subnodes available in my records loop? I need all the nodes that are under the dcterms namespace.
Here is the source xml:
<?xml version="1.0" encoding="UTF-8"?>
<searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/zing/srw/ srw-types.xsd">
<version>1.2</version>
<numberOfRecords>23</numberOfRecords>
<records>
<record>
<recordSchema>http://standaarden.overheid.nl/sru/</recordSchema>
<recordPacking>xml</recordPacking>
<recordData>
<gzd xmlns="http://standaarden.overheid.nl/sru" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:overheid="http://standaarden.overheid.nl/owms/terms/" xmlns:overheidrg="http://standaarden.overheid.nl/cvdr/terms/" xsi:schemaLocation="http://standaarden.overheid.nl/sru gzd.xsd">
<originalData>
<overheidrg:meta>
<owmskern>
<dcterms:identifier>123431_2</dcterms:identifier>
<dcterms:title>Ligplaatsenverordening 2009</dcterms:title>
<dcterms:language>nl</dcterms:language>
<dcterms:type scheme="overheid:Informatietype">regeling</dcterms:type>
<dcterms:creator scheme="overheid:Gemeente">Muiden</dcterms:creator>
<dcterms:modified>2015-08-27</dcterms:modified>
</owmskern>
<owmsmantel>
<dcterms:isFormatOf resourceIdentifier="">Onbekend</dcterms:isFormatOf>
<dcterms:alternative>Ligplaatsenverordening 2009</dcterms:alternative>
<dcterms:source resourceIdentifier="">artikel 149 van de Gemeentewet</dcterms:source>
<dcterms:isRatifiedBy scheme="overheid:BestuursorgaanGemeente">gemeenteraad</dcterms:isRatifiedBy>
<dcterms:subject>ruimtelijke ordening, verkeer en vervoer</dcterms:subject>
<dcterms:issued>2012-12-20</dcterms:issued>
</owmsmantel>
<cvdripm>
<overheidrg:inwerkingtredingDatum>2013-01-01</overheidrg:inwerkingtredingDatum>
<overheidrg:uitwerkingtredingDatum />
<overheidrg:betreft>Onbekend</overheidrg:betreft>
<overheidrg:kenmerk>Onbekend</overheidrg:kenmerk>
<overheidrg:onderwerp />
<overheidrg:gedelegeerdeRegelgeving><al >Geen</al></overheidrg:gedelegeerdeRegelgeving>
<overheidrg:redactioneleToevoeging><al >Geen</al></overheidrg:redactioneleToevoeging>
</cvdripm>
</overheidrg:meta>
</originalData>
<enrichedData>
<organisatietype>Gemeente</organisatietype>
<publicatieurl_xhtml>http://decentrale.regelgeving.overheid.nl/cvdr/xhtmloutput/Historie/Muiden/123431/123431_2.html</publicatieurl_xhtml>
<publicatieurl_xml>http://decentrale.regelgeving.overheid.nl/cvdr/xmloutput/Historie/Muiden/123431/123431_2.xml</publicatieurl_xml>
</enrichedData>
</gzd>
</recordData>
<recordPosition>1</recordPosition>
</record>
</records>
</searchRetrieveResponse>
You can use the SimpleXMLElement children method with the corresponding namespaces like children($ns['overheidrg']) and children($ns['dcterms']).
For example:
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/zing/srw/ srw-types.xsd">
<version>1.2</version>
<numberOfRecords>23</numberOfRecords>
<records>
<record>
<recordSchema>http://standaarden.overheid.nl/sru/</recordSchema>
<recordPacking>xml</recordPacking>
<recordData>
<gzd xmlns="http://standaarden.overheid.nl/sru" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:overheid="http://standaarden.overheid.nl/owms/terms/" xmlns:overheidrg="http://standaarden.overheid.nl/cvdr/terms/" xsi:schemaLocation="http://standaarden.overheid.nl/sru gzd.xsd">
<originalData>
<overheidrg:meta>
<owmskern>
<dcterms:identifier>123431_2</dcterms:identifier>
<dcterms:title>Ligplaatsenverordening 2009</dcterms:title>
<dcterms:language>nl</dcterms:language>
<dcterms:type scheme="overheid:Informatietype">regeling</dcterms:type>
<dcterms:creator scheme="overheid:Gemeente">Muiden</dcterms:creator>
<dcterms:modified>2015-08-27</dcterms:modified>
</owmskern>
<owmsmantel>
<dcterms:isFormatOf resourceIdentifier="">Onbekend</dcterms:isFormatOf>
<dcterms:alternative>Ligplaatsenverordening 2009</dcterms:alternative>
<dcterms:source resourceIdentifier="">artikel 149 van de Gemeentewet</dcterms:source>
<dcterms:isRatifiedBy scheme="overheid:BestuursorgaanGemeente">gemeenteraad</dcterms:isRatifiedBy>
<dcterms:subject>ruimtelijke ordening, verkeer en vervoer</dcterms:subject>
<dcterms:issued>2012-12-20</dcterms:issued>
</owmsmantel>
<cvdripm>
<overheidrg:inwerkingtredingDatum>2013-01-01</overheidrg:inwerkingtredingDatum>
<overheidrg:uitwerkingtredingDatum />
<overheidrg:betreft>Onbekend</overheidrg:betreft>
<overheidrg:kenmerk>Onbekend</overheidrg:kenmerk>
<overheidrg:onderwerp />
<overheidrg:gedelegeerdeRegelgeving><al >Geen</al></overheidrg:gedelegeerdeRegelgeving>
<overheidrg:redactioneleToevoeging><al >Geen</al></overheidrg:redactioneleToevoeging>
</cvdripm>
</overheidrg:meta>
</originalData>
<enrichedData>
<organisatietype>Gemeente</organisatietype>
<publicatieurl_xhtml>http://decentrale.regelgeving.overheid.nl/cvdr/xhtmloutput/Historie/Muiden/123431/123431_2.html</publicatieurl_xhtml>
<publicatieurl_xml>http://decentrale.regelgeving.overheid.nl/cvdr/xmloutput/Historie/Muiden/123431/123431_2.xml</publicatieurl_xml>
</enrichedData>
</gzd>
</recordData>
<recordPosition>1</recordPosition>
</record>
</records>
</searchRetrieveResponse>
XML;
$xml = new SimpleXMLElement($xml);
$ns = $xml->getNamespaces(true);
$xml->registerXPathNamespace('ns', $ns['']);
$xmlRecords = $xml->xpath('//ns:recordData');
foreach ($xmlRecords as $record)
{
$enrichedData = $record->gzd->enrichedData; //Yes! Works!
$originalData = $record
->gzd
->originalData
->children($ns['overheidrg'])
->meta
->children();
foreach ($originalData as $originalDataItem) {
// Get the children using the namespace 'dcterms'
$children = $originalDataItem->children($ns['dcterms']);
// Check for the name of the xml element
if ($originalDataItem->getName() === "owmskern") {
$identifier = $children->identifier->__toString();
// etc...
}
if ($originalDataItem->getName() === "owmsmantel") {
$isFormatOf = $children->isFormatOf->__toString();
// etc...
}
}
}

update node values of a XML with multiple child nodes from php

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());
?>

How to get the value of an xml sub element using DOMDocument methods?

I am new to PHP and XML.
Can somebody tell me how can I get the values of a sub element or child node of a an xml element?
index.php
$domdoc = new DOMDocument();
$domdoc->load('actionstars.xml');
foreach ($domdoc->getElementsByTagName("actionstar") as $star) {
echo $star->item(0)->nodeValue; // displays the <id> element
echo $star->item(1)->nodeValue; // displays the <name> element
echo "<br />";
}
actionstars.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<actionstars>
<actionstar>
<id>1</id>
<name>Jean Claude Van Damme</name>
</actionstar>
<actionstar>
<id>2</id>
<name>Scott Adkins</name>
</actionstar>
<actionstar>
<id>3</id>
<name>Dolph Ludgren</name>
</actionstar>
<actionstar>
<id>4</id>
<name>Michael Jai White</name>
</actionstar>
<actionstar>
<id>5</id>
<name>Michael Worth</name>
</actionstar>
</actionstars>
Pls help...
If you can guarantee their order, you can use childNodes and the offset, otherwise...
$domdoc = new DOMDocument();
$domdoc->load('actionstars.xml');
foreach ($domdoc->getElementsByTagName("actionstar") as $star) {
echo $shit->getElementsByTagName('id')->item(0)->nodeValue; // displays the <id> element
echo $shit->getElementsByTagName('name')->item(0)->nodeValue; // displays the <name> element
echo "<br />";
}

Categories