Reputation: 323
I have a really weird XML response and i need to extract it's data. I need to get the data in the "value" attribute but i need to choose them according to their "key" attributes.
This is how it looks like
<phone>
2125556666
</phone>
<State>
ny
</State>
<Response>
<data key="Supported" value="Yes"/>
<data key="Host" value="Remote"/>
<data key="WholeProductList">
<data key="Product" value="a-z44"/>
<data key="Product" value="c-k99"/>
<data key="Product" value="e-b089"/>
<data key="Product" value="z-p00"/>
<data key="Product" value="r-333"/>
<data key="Product" value="t-RS232"/>
<data key="Product" value="4-lve"/>
<data key="Product" value="Shutdown"/>
</data>
</Response>
In PHP i currenty have
$xmltmp = new DomDocument;
$xmltmp->loadXml($response);
$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;
echo $phone;
echo $state;
This currently outputs both phone number and state. It works fine.
Now i need to know if the "Supported" key's value is Yes or No, and if it's Yes, i need to get all "Products". I'm kinda stuck because i am having a hard time making the foreach statement and then checking the "key" attribute value.
Thanks!
Upvotes: 1
Views: 429
Reputation: 19502
Your XML is invalid. An XML document always needs a single document element node.
Example:
<root>
<phone>2125556666</phone>
<State>ny</State>
<Response>
<data key="Supported" value="Yes"/>
...
</data>
</Response>
</root>
The easiest way to fetch data from a DOM is XPath. In PHP that is provided by the DOMXPath
class and part of the ext/dom
. DOMXPath::evaluate()
allows you to fetch node lists or scalar values from the DOM document.
$dom = new DOMDocument;
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$phone = $xpath->evaluate('string(/*/phone)');
$state = $xpath->evaluate('string(/*/State)');
var_dump($phone, $state);
Output:
string(10) "2125556666"
string(2) "ny"
An expression like /*/phone
selects all phone
element child nodes inside the document element. string(/*/phone)
casts the first found node into a string and return that. If no node was found, it will return an empty string.
The XPath expression for the supported status is slightly more complex. Conditions for nodes are provided in []
. It is possible to compare the result directly in XPath. The return value will be an boolean.
$supported = $xpath->evaluate('/*/Response/data[@key="Supported"]/@value = "Yes"');
var_dump($supported);
Output:
bool(true)
If the expression returns a node list you can iterate it with foreach()
.
$nodes = $xpath->evaluate(
'/*/Response/data[@key="WholeProductList"]/data[@key="Product"]/@value'
);
$products = [];
foreach ($nodes as $attributeNode) {
$products[] = $attributeNode->value;
}
var_dump($products);
Output:
array(8) {
[0]=>
string(5) "a-z44"
[1]=>
string(5) "c-k99"
[2]=>
string(6) "e-b089"
[3]=>
string(5) "z-p00"
[4]=>
string(5) "r-333"
[5]=>
string(7) "t-RS232"
[6]=>
string(5) "4-lve"
[7]=>
string(8) "Shutdown"
}
Upvotes: 3
Reputation: 8472
This won't quite work "as is" since I don't know what the actual structure of the XML document is, but in short you map the XML nodes to XPath like //root/node/child_node/@attribute
and so on.
It should also have some sanity (not null) type checking in.
$xmltmp = new DomDocument;
$xmltmp->loadXml($response);
$xQuery = new DOMXPath($xmltmp);
//not sure what your root node is so the query path is probably wrong
$supported = $xQuery->query('/Response/data[@key="Supported"]/@value')->value;
You can also replace:
$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;
With something like (again - without the full structure of the XML document the path itself is probably not quite right):
$phone = $xQuery->query('/phone')->item(0)->nodeValue;
$state = $xQuery->query('/State')->item(0)->nodeValue;
Upvotes: 1