So i am hitting a soap service, when i get the data and parse it through simplexml_load_string in order to access the data as an object (or just basically access the data) simplexml_load_string seems to strip it out.
A Raw response from soap service looks like:
A result parsed through simplexml_load_string
using the following code:
$result = simplexml_load_string((string)$result->DisplayCategoriesResult->any);
i get a result of:
this looks correct but at a closer look you will notice its just id's and the names of the categories are left behing simplexml_load_string
how can i manage to get the proper result? if there is another way of getting the raw data into a "usable" form or object that solution is also welcome
The text content of XML nodes doesn't show up when using print_r or var_dump, etc. They aren't "traditional" PHP objects, so you can't use the standard debugging options.
To access the text content (whether embedded as CDATA or otherwise), you need to step down into the child elements, and then cast them to strings:
<?php
$xml = <<<XML
<randgo xmlns="">
<status>0</status>
<message>Success</message>
<categories>
<category id="53"><![CDATA[go eat]]></category>
<category id="54"><![CDATA[go do]]></category>
<category id="55"><![CDATA[go out]]></category>
</categories>
</randgo>
XML;
$sxml = simplexml_load_string($xml);
foreach ($sxml->categories->category as $category)
{
echo $category['id'] . ": " . (string) $category, PHP_EOL;
}
=
$ php simplexml_categories.php
53: go eat
54: go do
55: go out
See: https://eval.in/590975
(Sorry if there are any typos in the XML, I think I copied from the screenshot correctly...)
The category names are CDATA. Try something like this to read it.
$doc = new DOMDocument();
$doc->load((string)$result->DisplayCategoriesResult->any);
$categories = $doc->getElementsByTagName("categories");
foreach ($categories as $categorie) {
foreach($categorie->childNodes as $child) {
if ($child->nodeType == XML_CDATA_SECTION_NODE) {
echo $child->textContent . "<br/>";
}
}
}
Related
Need help with updating some simplexml code I did along time ago. The XML file I'm parsing from is formatted in a new way, but I can't figure out how to navigate it.
Example of old XML format:
<?xml version="1.0" encoding="UTF-8"?>
<pf version="1.0">
<pinfo>
<pid><![CDATA[test1 pid]]></pid>
<picture><![CDATA[http://test1.image]]></picture>
</pinfo>
<pinfo>
<pid><![CDATA[test2 pid]]></pid>
<picture><![CDATA[http://test2.image]]></picture>
</pinfo>
</pf>
and then the new XML format (note "category name" added):
<?xml version="1.0" encoding="UTF-8"?>
<pf version="1.2">
<category name="Cname1">
<pinfo>
<pid><![CDATA[test1 pid]]></pid>
<picture><![CDATA[http://test1.image]]></picture>
</pinfo>
</category>
<category name="Cname2">
<pinfo>
<pid><![CDATA[test2 pid]]></pid>
<picture><![CDATA[http://test2.image]]></picture>
</pinfo>
</category>
</pf>
And below the old code for parsing that doesn't work since the addition of "category name" in the XML:
$pinfo = new SimpleXMLElement($_SERVER['DOCUMENT_ROOT'].'/xml/file.xml', null, true);
foreach($pinfo as $resource)
{
$Profile_id = $resource->pid;
$Image_url = $resource->picture;
// and then some echo´ing of the collected data inside the loop
}
What do I need to add or do completely different? I tried with xpath,children and sorting by attributes but no luck - SimpleXML has always been a mystery to me :)
You were iterating over all <pinfo> elements located in the root element previously:
foreach ($pinfo as $resource)
Now all <pinfo> elements have moved from the root element into the <category> elements. You now need to query those elements first:
foreach ($pinfo->xpath('/*/category/pinfo') as $resource)
The now wrong named variable $pinfo is standing a bit in the way so it better do some more changes:
$xml = new SimpleXMLElement($_SERVER['DOCUMENT_ROOT'].'/xml/file.xml', null, true);
$pinfos = $xml->xpath('/*/category/pinfo');
foreach ($pinfos as $pinfo) {
$Profile_id = $pinfo->pid;
$Image_url = $pinfo->picture;
// ... and then some echo´ing of the collected data inside the loop
}
The category elements exist as their own array when you load the XML file. The XML you are used to parsing is contained within. All you need to do is wrap your current code with another foreach. Other than that there isn't much to change.
foreach($pinfo as $category)
{
foreach($category as $resource)
{
$Profile_id = $resource->pid;
$Image_url = $resource->picture;
// and then some echo´ing of the collected data inside the loop
}
}
If I use the following php code to convert an xml to json:
<?php
header("Content-Type:text/json");
$resultXML = "
<QUERY>
<Company>fcsf</Company>
<Details>
fgrtgrthtyfgvb
</Details>
</QUERY>
";
$sxml = simplexml_load_string($resultXML);
echo json_encode($sxml);
?>
I get
{"Company":"fcsf","Details":"\n fgrtgrthtyfgvb\n "}
However, If I use CDATA in the Details element as follows:
<?php
header("Content-Type:text/json");
$resultXML = "
<QUERY>
<Company>fcsf</Company>
<Details><![CDATA[
fgrtgrthtyfgvb]]>
</Details>
</QUERY>
";
$sxml = simplexml_load_string($resultXML);
echo json_encode($sxml);
?>
I get the following
{"Company":"fcsf","Details":{}}
In this case the Details element is blank. Any idea why Details is blank and how to correct this?
This is not a problem with the JSON encoding – var_dump($sxml->Details) shows you that SimpleXML already messed it up before, as you will only get
object(SimpleXMLElement)#2 (0) {
}
– an “empty” SimpleXMLElement, the CDATA content is already missing there.
And after we figured that out, googling for “simplexml cdata” leads us straight to the first user comment on the manual page on SimpleXML Functions, that has the solution:
If you are having trouble accessing CDATA in your simplexml document, you don't need to str_replace/preg_replace the CDATA out before loading it with simplexml.
You can do this instead, and all your CDATA contents will be merged into the element contents as strings.
$xml = simplexml_load_file($xmlfile, 'SimpleXMLElement', LIBXML_NOCDATA);
So, use
$sxml = simplexml_load_string($resultXML, 'SimpleXMLElement', LIBXML_NOCDATA);
in your code, and you’ll get
{"Company":"fcsf","Details":"\n fgrtgrthtyfgvb\n "}
after JSON-encoding it.
I have a page in php where I have to parse an xml.
I have done this for example:
$hotelNodes = $xml_data->getElementsByTagName('Hotel');
foreach($hotelNodes as $hotel){
$supplementsNodes2 = $hotel->getElementsByTagName('BoardBase');
foreach($supplementsNodes2 as $suppl2) {
echo'<p>HERE</p>'; //not enter here
}
}
}
In this code I access to each hotel of my xml, and foreach hotel I would like to search the tag BoardBase but it doesn0t enter inside it.
This is my xml (cutted of many parts!!!!!)
<hotel desc="DESC" name="Hotel">
<selctedsupplements>
<boardbases>
<boardbase bbpublishprice="0" bbprice="0" bbname="Colazione Continentale" bbid="1"></boardbase>
</boardbases>
</selctedsupplements>
</occupancy></occupancies>
</hotel>
I have many nodes that doesn't have BoardBase but sometimes there is but not enter.
Is possible that this node isn't accessible?
This xml is received by a server with a SoapClient.
If I inspect the XML printed in firebug I can see the node with opacity like this:
I have also tried this:
$supplementsNodes2 = $hotel->getElementsByTagName('boardbase');
but without success
2 issues I can see from the get-go: XML names are case-sensitive, hence:
$hotelNodes = $xml_data->getElementsByTagName('Hotel');
Can't work, because your xml node looks like:
<hotel desc="DESC" name="Hotel">
hotel => lower-case!
As you can see here:
[...] names for such things as elements, while XML is explicitly case sensitive.
The official specs specify tag names as case-sensitive, so getElementsByTagName('FOO') won't return the same elements as getElementsByTagName('foo')...
Secondly, you seem to have some tag-soup going on:
</occupancy></occupancies>
<!-- tag names don't match, both are closing tags -->
This is just plain invalid markup, it should read either:
<occupancy></occupancy>
or
<occupancies></occupancies>
That would be the first 2 ports of call.
I've set up a quick codepad using this code, which you can see here:
$xml = '<hotel desc="DESC" name="Hotel">
<selctedsupplements>
<boardbases>
<boardbase bbpublishprice="0" bbprice="0" bbname="Colazione Continentale" bbid="1"></boardbase>
</boardbases>
</selctedsupplements>
<occupancy></occupancy>
</hotel>';
$dom = new DOMDocument;
$dom->loadXML($xml);
$badList = $dom->getElementsByTagName('Hotel');
$correctList = $dom->getElementsByTagName('hotel');
echo sprintf("%d",$badList->lenght),
' compared to ',
$correctList->length, PHP_EOL;
The output was "0 compared to 1", meaning that using a lower-case selector returned 1 element, the one with the upper-case H returned an empty list.
To get to the boardbase tags for each hotel tag, you just have to write this:
$hotels = $dom->getElementsByTagName('html');
foreach($hotels as $hotel)
{
$supplementsNodes2 = $hotel->getElementsByTagName('boardbase');
foreach($supplementsNodes2 as $node)
{
var_dump($node);//you _will_ get here now
}
}
As you can see on this updated codepad.
Alessandro, your XML is a mess (=un casino), you really need to get that straight. Elias' answer pointed out some very basic stuff to consider.
I built on the code pad Elias has been setting up, it is working perfectly with me:
$dom = new DOMDocument;
$dom->loadXML($xml);
$hotels = $dom->getElementsByTagName('hotel');
foreach ($hotels as $hotel) {
$bbs = $hotel->getElementsByTagName('boardbase');
foreach ($bbs as $bb) echo $bb->getAttribute('bbname');
}
see http://codepad.org/I6oxkEOC
I need to display data from an external XML feed on my site but I have absolutely no idea where to start. What would be the full PHP code to grab the XML feed and print the following elements into my page:
<name></name>
<status></status>
<pin></pin>
<picture>
</picture>
<description></description>
<category name="skills">
<skill></skill>
</category>
<category name="tools">
<tool></tool>
<tool></tool>
<tool></tool>
</category>
<category name="subjects">
<subject></subject>
</category>
You can use php built in function called simplexml_load_string along with file_get_contents.
What the two functions do is convert the url xml feed to a string and then create an object stored into $xml.
Resource file_get_contents
Resource simplexml_load_string
$url = 'yourXMLfeed.xml';
$xml = file_get_contents($url);
$xml = simplexml_load_string($xml);
You can then access your data inside <name></name>, etc like so:
echo $xml->name will print the data inside of the name tags.
If you have a nested xml feed you can also use foreach like so:
foreach($xml as $x):
echo $x->name
endforeach;
EDIT
Let say each of your <tool></tool> had data ie:
<tool>Wrench</tool> <tool>Hammer</tool> <tool>Screwdriver</tool>
You could do a quick foreach loop to get the data like so:
foreach($xml->category[1] as $tool) {
echo $tool.' ';
}
This would echo out Wrench Hammer Screwdriver
I have an xml file that I need to parse through and get values. Below is a snippit of xml
<?xml version="1.0"?>
<mobile>
<userInfo>
</userInfo>
<CATALOG>
<s0>
<SUB0>
<DESCR>Paranormal Studies</DESCR>
<SUBJECT>147</SUBJECT>
</SUB0>
</s0>
<sA>
<SUB0>
<DESCR>Accounting</DESCR>
<SUBJECT>ACCT</SUBJECT>
</SUB0>
<SUB1>
<DESCR>Accounting</DESCR>
<SUBJECT>ACCTG</SUBJECT>
</SUB1>
<SUB2>
<DESCR>Anatomy</DESCR>
<SUBJECT>ANATOMY</SUBJECT>
</SUB2>
<SUB3>
<DESCR>Anthropology</DESCR>
<SUBJECT>ANTHRO</SUBJECT>
</SUB3>
<SUB4>
<DESCR>Art</DESCR>
<SUBJECT>ART</SUBJECT>
</SUB4>
<SUB5>
<DESCR>Art History</DESCR>
<SUBJECT>ARTHIST</SUBJECT>
</SUB5>
</sA>
So, I need to grab all the child elements of <sA> and then there are more elements called <sB> etc
But I do not know how to get all of the child elements with <sA>, <sB>, etc.
How about this:
$xmlstr = LoadTheXMLFromSomewhere();
$xml = new simplexml_load_string($xmlstr);
$result = $xml->xpath('//sA');
foreach ($result as $node){
//do something with node
}
PHP does have a nice class to access XML, which is called SimpleXml for a reason, consider heavily using that if your code is going to access only a part of the XML (aka query the xml). Also, consider doing queries using XPath, which is the best way to do it
Notice that I did the example with sA nodes only, but you can configure your code for other node types really easily.
Hope I can help!
you should look into simplexml_load_string() as I'm pretty sure it would make your life a lot easier. It returns a StdObject that you can use like so:
$xml = simplexml_load_string(<your huge xml string>);
foreach ($xml->hpt_mobile->CATALOG->sA as $value){
// do things with sA children
}
$xml = new DOMDocument();
$xml->load('path_to_xml');
$htp = $xml->getElementsByTagName('hpt_mobile')[0];
$catalog = $htp->getElementsByTagName('CATALOG')[0]
$nodes = $catalog->getElementsByTagName('sA')->childNodes;