I must be missing something simple here and it's driving me crazy.
I'm making a call to a web services api and getting back some xml:
<?xml version="1.0" encoding="utf-16"?>
<MTSMember xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LastName>Smith</LastName>
<FirstName>john</FirstName>
<MemberNo>xxxxxxxx</MemberNo>
<Club>None</Club>
<JoinDate>2013-05-14</JoinDate>
<Email>email#email.com</Email>
</MTSMember>
I then need to process this xml to get the email address. but I'm just getting an empty result using the code below:
$xml_result = simplexml_load_string($xml_string_above);
echo $xml_result->MTSMember[0]->Email;
Can someone point me in the right direction. I've read through several other answers trying out various solutions, but can't seem to get it to work.
Edit: This was the last tutorial i tried out http://blog.teamtreehouse.com/how-to-parse-xml-with-php5
That should be:
echo $xml_result->Email;
Because simplexml_load_string() is loading MTSMember as main SimpleXMLElement.
Codepad Example
Try this
$xml=new SimpleXMLElement($str);
$result=$xml->xpath('//Email');
foreach ($result as $Email)
echo $Email . "<br>";
simply
$xml=new SimpleXMLElement($str);
echo $xml[0]->Email;
update:
The below just for your comment , the whole what i tried
$str='<?xml version="1.0" encoding="utf-8"?>
<MTSMember xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LastName>Smith</LastName>
<FirstName>john</FirstName>
<MemberNo>xxxxxxxx</MemberNo>
<Club>None</Club>
<JoinDate>2013-05-14</JoinDate>
<Email>email#email.com</Email>
</MTSMember>';
$xml=new SimpleXMLElement($str);
echo $xml[0]->Email;
//OR
$xml=new SimpleXMLElement($str);
$result=$xml->xpath('//Email');
foreach ($result as $Email)
echo $Email . "<br>";
Be happy :)
This should work fine
$xml = new SimpleXMLElement($xml_string_above);
$dc = $xml->email;
echo $dc;
Related
I tried to parse this using lots of way I found but could't parse this.
<?xml version="1.0" encoding="UTF-16"?>
<iBridge xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<User ID="162715" TOKEN="ABE02FD9-89FA-47F4-B687-E75D7AB63F4B" USER_COOKIE="ASP.NET_SessionId=g2b3pl453rmbatjpsitjz255|Login=|Login=8D34CBFE9FD0108D506BD78D42E76CB0B424FB1335DA48E8AA52D11466BAC8EE55FABB019D1C81E6A7E91A62E47C3DE049CB9C3BFBC680F50208282F8BA2451C2202585E49D62F1A" FULL_NAME="Sachin Kumar" FIRST_NAME="Sachin" LAST_NAME="Kumar" COMPANY="Unikove" LAST_FIRST="KUMAR, SACHIN" ADDRESS_1="Address One" ADDRESS_2="" CITY="My City" STATE_PROVINCE="AE" ZIP="90001" COUNTRY="" PREFERRED_MAIL="1" PREFERRED_BILL="1" CO_ID="" MEMBER_TYPE="WEB" MEMBER_TYPE_DESCRIPTION="Web Sign-Up" EMAIL="sachin.kumar#unikove.com" ASSIGNMENT="" />
</iBridge>
if you save your xml file in the root of your php script and call it my_xml.xml , the php script would be :
<?php
$iBridge = simplexml_load_file('my_xml.xml');
foreach ($iBridge as $userinfo){
$id = $userinfo['ID'];
$token = $userinfo['TOKEN'];
$user_cookie = $userinfo['USER_COOKIE'];
echo "ID: '".$id."<br/>TOKEN: ".$token."<br/>USER COOKIE: ".$user_cookie."<br/>";
}
?>
You can add the rest of properties yourself just like the pattern above, FIRST_NAME, LAST_NAME,etc..
So I'm getting an xml file back from a soap service (of which I have no control over). It's returning back an xmlns which is causing simpleXML issues. I'm running a str_replace to get rid of that issue, however now simpleXML just returns an empty object. XML structure appears to be fine, no errors just an empty object.
$xmlString = $client->__getLastResponse();
$feed = str_replace(' xmlns="LMSWebservice"', '', $xmlString);
$sData= simplexml_load_string($feed);
print_r($sData);
Returns: SimpleXMLElement Object()
XML source before str replace is:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUserInternalIDByPersonalIDResponse xmlns="LMSWebservice">
<GetUserInternalIDByPersonalIDResult>
<Response xmlns="">
<Timestamp date="24/10/2013" time="04:27:37" />
<User>
<UserInternalID>4907</UserInternalID>
</User>
</Response>
</GetUserInternalIDByPersonalIDResult>
</GetUserInternalIDByPersonalIDResponse>
</soap:Body>
</soap:Envelope>
After str replace:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUserInternalIDByPersonalIDResponse>
<GetUserInternalIDByPersonalIDResult>
<Response xmlns="">
<Timestamp date="24/10/2013" time="04:27:37" />
<User>
<UserInternalID>4907</UserInternalID>
</User>
</Response>
</GetUserInternalIDByPersonalIDResult>
</GetUserInternalIDByPersonalIDResponse>
</soap:Body>
</soap:Envelope>
Any help would be greatly appreciated, this is driving me crazy!
----So if I don't get rid of the namespace attribute I get this error message:
Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser warning : xmlns: URI LMSWebservice is not absolute in serviceTest2.php on line 16
Warning: simplexml_load_string() [function.simplexml-load-string]: LSchema"><soap:Body><GetUserInternalIDByPersonalIDResponse xmlns="LMSWebservice" in serviceTest2.php on line 16
Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in serviceTest2.php on line 16
If I try using xPath to get at UserInternalID it returns an empty array. If what you're saying is correct and this is going into simpleXML correctly, then how do I access the UserInternalID node? Sorry, this is the first time using simpleXML and this is just perplexing me.
So just tried changing the NS
$feed = str_replace('xmlns="LMSWebservice"', 'xmlns="ns:LMSWebservice"', $xmlString);
which goes in without errors.
I tried this for the xPath
$ID = $sData->xpath('UserInternalID');
I understand this is probably completely wrong, but I haven't tried much else with this as it didn't seem to be going into simpleXML correctly in the first place. :/
So I've used
$ID = $sData->xpath('//UserInternalID');
echo $ID[0];
Which works perfectly. Thank you for all your help!
Through the extensive comments and your last edit finally the actual cause of your problem could be revealed, the xpath expression is wrong:
$ID = $sData->xpath('UserInternalID');
Wrong with it is the path, this matches no elements. Instead you could use:
$ID = (string) $xml->xpath('//UserInternalID')[0];
Or more verbose:
$ID = (string) $xml->xpath('//Response/User/UserInternalID')[0];
Key point here is that you write the correct path to the element you would like to query for.
Complete usage example:
<?php
/**
* SoapClient xml return string with simpleXML
*
* #link http://stackoverflow.com/q/19556414/367456
*/
$response = <<<RESPONSE
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUserInternalIDByPersonalIDResponse xmlns="LMSWebservice">
<GetUserInternalIDByPersonalIDResult>
<Response xmlns="">
<Timestamp date="24/10/2013" time="04:27:37" />
<User>
<UserInternalID>4907</UserInternalID>
</User>
</Response>
</GetUserInternalIDByPersonalIDResult>
</GetUserInternalIDByPersonalIDResponse>
</soap:Body>
</soap:Envelope>
RESPONSE;
$restore = libxml_use_internal_errors(TRUE);
$xml = simplexml_load_string($response);
libxml_use_internal_errors($restore);
echo $xml->xpath('//Response/User/UserInternalID')[0];
Output:
4907
Online Demo: https://eval.in/57149
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($response);
libxml_clear_errors();
$xml = $doc->saveXML($doc->documentElement);
$xml = simplexml_load_string($xml);
Use this helped me in a big way.
I am trying to get the PAY where it has the ID 3 Where it says the label phone
but i really dont know how, i tried everything.
Thanks for helping!
Here is the XML code:
$books = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data>
<login>1</login>
<arrStatsData>
<item>
<Id>500</Id>
<Label>website_name</Label>
<Data>
<item>
<Id>4</Id>
<Label>transactions</Label>
<Data>
<sum>2029.34</sum>
<cst>47.67575</cst>
<num>86</num>
<avg>23.6</avg>
<pay>1981.66</pay>
</Data>
</item>
<item>
<Id>3</Id>
<Label>Phone</Label>
<Data>
<sum>205</sum>
<cst>17.353</cst>
<num>205</num>
<avg>1</avg>
<pay>187.647</pay>
</Data>
</item>
......
PHP Code:
$xml = simplexml_load_string($arrResult); //load xml from above
foreach($xml->arrStatsData->item->Data as $item)
{
foreach($item->item as $DATA)
{
echo $DATA->Id.'<br>';
}
My result now is:
1981.66
187.647
-0.4448
Since you know some information that's tell the node apart from the rest you can use XPath to get the value directly instead of iterating through all of them:
<?php
$sxe = new SimpleXMLElement($books);
$pay = $sxe->xpath('//item[./Id=3]/Data/pay');
echo (string) $pay[0];
Ouput:
187.647
Your PHP code would be like this:
$xml = simplexml_load_string($books);
foreach($xml->arrStatsData->item->Data as $item)
{
//echo '$item;';
foreach($item->item as $DATA)
{
if($DATA->Id == '3'){
echo $DATA->Data->pay."<br/>";
}
}
}
It retrieve the pay value when the ID is equals to 3.
Rolando Isidoro was faster to recommend xpath, my solution is slightly different, that's why I post it, too:
$pay = (string)$xml->xpath("//item[Id = '3']/Data/pay")[0];
echo $pay;
see it working: http://codepad.viper-7.com/qzPlmp
I am trying to get to a part in an xml response, without following the whole path. Now I know that xpath has search abilities, but somehow I dont understand it... :(
The XML i am parsing is this:
<?xml version="1.0" encoding="utf-8"?>
<soapEnvelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<envHeader xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsaAction>http://www.rechtspraak.nl/namespaces/cir01/searchUndertakingResponse</wsaAction>
<wsaMessageID>urn:uuid:11f7d4cd-2280-4298-85eb-dadf5bd743f1</wsaMessageID>
<wsaRelatesTo>urn:uuid:59630fbd-b990-4020-9c1c-822c58186d96</wsaRelatesTo>
<wsaTo>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsaTo>
<wsseSecurity>
<wsuTimestamp wsu:Id="Timestamp-df25f141-fed2-47ed-967e-93cd04d1c8f2">
<wsuCreated>2011-04-02T06:52:52Z</wsuCreated>
<wsuExpires>2011-04-02T06:57:52Z</wsuExpires>
</wsuTimestamp>
</wsseSecurity>
</envHeader>
<soapBody>
<searchUndertakingResponse xmlns="http://www.rechtspraak.nl/namespaces/cir01"><searchUndertakingResult>
<publicatieLijst xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" extractiedatum="2011-04-02T08:52:51" xmlns="http://www.rechtspraak.nl/namespaces/inspubber01">
<publicatieKenmerk>sgr.10.787.F.1300.1.10</publicatieKenmerk>
<publicatieKenmerk>utr.10.585.F.1300.1.10</publicatieKenmerk>
</publicatieLijst>
</searchUndertakingResult>
</searchUndertakingResponse>
</soapBody>
</soapEnvelope>
And I am looking for these values: <publicatieKenmerk>sgr.10.787.F.1300.1.10</publicatieKenmerk> <publicatieKenmerk>utr.10.585.F.1300.1.10</publicatieKenmerk>
Now this works:
$lijst = $results->soapBody->searchUndertakingResponse->searchUndertakingResult->publicatieLijst->publicatieKenmerk;
foreach ($lijst AS $kenmerk) {
echo $kenmerk."<BR>";
}
But I dont want to use this, as I need to be flexible for other results. and cannot rely on
searchUndertakingResponse->searchUndertakingResult
So I was hoping to use xpath to get there, but this doesnt work:
$lijst = $results->xpath('//publicatieKenmerk');
foreach($lijst as $kenmerk) {
echo $kenmerk."<br />";
}
But I thought relative would work as well... any ideas?
You'll notice that your <publicatieLijst> node has a default namespace set: xmlns="http://www.rechtspraak.nl/namespaces/inspubber01" which means that <publicatieKenmerk> exists that namespace. That's why //publicatieKenmerk won't find it, you have to search in the right namespace.
For that, you can register the namespace with your own prefix and use that prefix in the following XPath query, like this:
$soapEnvelope = simplexml_load_string($xml);
$soapEnvelope->registerXPathNamespace(
'inspubber01',
'http://www.rechtspraak.nl/namespaces/inspubber01'
);
foreach ($soapEnvelope->xpath('//inspubber01:publicatieKenmerk') as $publicatieKenmerk)
{
echo $publicatieKenmerk, "\n";
}
can you try to change on they way it loops?
while(list( , $node) = each($lijst)) {
echo 'kenmerk: ',$node,"\n";
}
After spending SEVERAL frustrated hours on this I am asking for your help.
I am trying to get the content of particular nodes from a SOAP response.
The response is
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"<xmlns:ns1="http://soap.xxxxxx.co.uk/">
<env:Body>
<ns1:PlaceOrderResponse>
<xxxxxOrderNumber></xxxxxOrderNumber>
<ErrorArray>
<Error>
<ErrorCode>24</ErrorCode>
<ErrorText>The+client+order+number+3002254+is+already+in+use</ErrorText>
</Error>
<Error>
<ErrorCode>1</ErrorCode>
<ErrorText>Aborting</ErrorText>
</Error>
</ErrorArray>
</ns1:PlaceOrderResponse>
</env:Body>
</env:Envelope>
I am trying to get at the nodes and children of <ErrorArray>.
Because of the XML containing namespaces
$XmlArray = new SimpleXMLElement($XmlStr);
foreach ($XmlArray->env:Envelope->env:Body->ns1:PlaceOrderResponse->ErrorArray->Error as $Error)
{
echo $Error->ErrorCode."<br />";
}
doesn't work.
I have read a number of articles such as
http://www.sitepoint.com/blogs/2005/10/20/simplexml-and-namespaces/
http://blog.stuartherbert.com/php/2007/01/07/using-simplexml-to-parse-rss-feeds/
and about 20 questions on this site, which unfortunately are not helping.
Even writing,
$XmlArray = new SimpleXMLElement($XmlStr);
echo "<br /><br /><pre>\n";
print_r($XmlArray);
echo "<pre><br /><br />\n";
gives
SimpleXMLElement Object
(
)
which makes me wonder if the soap response ($XmlStr) is actually a valid input for SimpleXMLElement.
It seems that the line
$XmlArray = new SimpleXMLElement($XmlStr);
is not doing what I expect it to.
Any help on how to get the nodes from the XML above would be very welcome.
Obviously getting it to work (having a working example) is what I need in the short term, but if someone could help me understand what I am doing wrong would be better in the long term.
Cheers.
Stu
You have to use SimpleXMLElement::children(), though at this point it would probably be easier to use XPath.
<?php
$XmlStr = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://soap.xxxxxx.co.uk/" >
<env:Body>
<ns1:PlaceOrderResponse>
<xxxxxOrderNumber></xxxxxOrderNumber>
<ErrorArray>
<Error>
<ErrorCode>24</ErrorCode>
<ErrorText>The+client+order+number+3002254+is+already+in+use</ErrorText>
</Error>
<Error>
<ErrorCode>1</ErrorCode>
<ErrorText>Aborting</ErrorText>
</Error>
</ErrorArray>
</ns1:PlaceOrderResponse>
</env:Body>
</env:Envelope>
XML;
$XmlArray = new SimpleXMLElement($XmlStr);
$t = $XmlArray->children("env", true)->Body->
children("ns1", true)->PlaceOrderResponse->
children()->ErrorArray->Error;
foreach ($t as $error) {
echo $error->ErrorCode, " " , $error->ErrorText, "<br />";
}
gives:
24 The+client+order+number+3002254+is+already+in+use
1 Aborting
A cheap and nasty way is to just simply remove the prefixes:
$xml = preg_replace('%<(\/)?(\S+):(\w+)%', '<$1$3', $xml);