PHP xPath parsing SOAP
I have a SOAP request that has a body like the code below. (I have removed the unrelevant nodes). I only want to parse the request for the NumInfo nodes that have a NumType of HI. I need to get the Type, Num, Desc, Quantity and PriceInfo values for the nodes that have a NumInfo node with NumType = HI.
Using xpath to get the nodes like this:
$xml = simplexml_load_file('RequestExample.xml');
$xml->registerXPathNamespace("bms", "http://www.cieca.com/BMS");
$xml->xpath("//bms:Selected[contains(., 'HI')]")
would get the Selected node(s) containing the HI. xpath
returns an array of SimpleXML Objects, correct?
How do I get the other info for the parent corresponding to that NumInfo node? Also, by Registering the namespace, shouldn't I be able to omit them in my xpath queries?
<soap:Body>
<bms:ProcurementAddRq>
<bms:ProcurementFolder>
<bms:ProcurementInfo>
<bms:ProcurementList>
<bms:Procurement>
<bms:Selected>
<bms:NumInfo>
<bms:NumType>OE</bms:NumType>
<bms:Num>04715SNAA90ZZ</bms:Num>
</bms:NumInfo>
<bms:NumInfo>
<bms:NumType>HI</bms:NumType>
<bms:Num>187-01436</bms:Num>
</bms:NumInfo>
<bms:NumInfo>
<bms:NumType>HPT</bms:NumType>
<bms:Num>187</bms:Num>
</bms:NumInfo>
<bms:Type>PAN</bms:Type>
<bms:Desc>Cover</bms:Desc>
<bms:Quantity>1</bms:Quantity>
<bms:PriceInfo>
<bms:UnitListPrice>328.42</bms:UnitListPrice>
<bms:UnitNetPrice>328.42</bms:UnitNetPrice>
</bms:PriceInfo>
</bms:Selected>
</bms:Procurement>
<bms:Procurement>
<bms:Selected>
<bms:NumInfo>
<bms:NumType>OE</bms:NumType>
<bms:Num>71570SNAA00</bms:Num>
</bms:NumInfo>
<bms:Type>PAN</bms:Type>
<bms:Desc>Abs</bms:Desc>
<bms:Quantity>1</bms:Quantity>
<bms:PriceInfo>
<bms:UnitListPrice>49.80</bms:UnitListPrice>
<bms:UnitNetPrice>49.80</bms:UnitNetPrice>
</bms:PriceInfo>
</bms:Selected>
</bms:Procurement>
<bms:Procurement>
<bms:Selected>
<bms:NumInfo>
<bms:NumType>OE</bms:NumType>
<bms:Num>66100SNEA00ZZ</bms:Num>
</bms:NumInfo>
<bms:Type>PAN</bms:Type>
<bms:Desc>Panel</bms:Desc>
<bms:Quantity>1</bms:Quantity>
<bms:PriceInfo>
<bms:UnitListPrice>355.83</bms:UnitListPrice>
<bms:UnitNetPrice>355.83</bms:UnitNetPrice>
</bms:PriceInfo>
</bms:Selected>
<bms:Procurement>
<bms:Selected>
<bms:NumInfo>
<bms:NumType>OE</bms:NumType>
<bms:Num>04655SNE305ZZ</bms:Num>
</bms:NumInfo>
<bms:Type>PAP</bms:Type>
<bms:Desc>Pan</bms:Desc>
<bms:Quantity>1</bms:Quantity>
<bms:PriceInfo>
<bms:UnitListPrice>994.13</bms:UnitListPrice>
<bms:UnitNetPrice>994.13</bms:UnitNetPrice>
</bms:PriceInfo>
</bms:Selected>
</bms:ProcurementList>
</bms:ProcurementInfo>
</bms:ProcurementFolder>
</bms:ProcurementAddRq>
</soap:Body>
You should be able to get the data using...
$selected = $xml->xpath("//bms:Selected[bms:NumInfo/bms:NumType='HI']")[0];
echo (string)$selected->children("bms",true)->Desc;
Note the [0]
at the end of the XPath function, this is as you say because it returns a list of the nodes that match. Normally you would use this in a foreach()
but if there is only one, then you can shorten it this way.
When you fetch a node, this is actually a SimpleXMLElement, using (string)
casts the value to a string, allowing you more flexibility in using it as a value (echo
does this anyway, but this is just to show the principle)
The ->children("bms",true)
bit returns all of the child nodes in the namespace (using a prefix) and this allows you to use ->Desc
without the prefix.
Even if you register the namespace, you still need to use it in your XPath statements, this allows you to mix namespaces and elements. You may have the same named element but a different namespace, so this ensures your referring to the right one.