У меня действительно странный XML-ответ, и мне нужно извлечь его данные. Мне нужно получить данные в атрибуте «value», но мне нужно выбрать их в соответствии с их атрибутами «key».
Вот так это выглядит
<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>
В PHP у меня есть
$xmltmp = new DomDocument;
$xmltmp->loadXml($response);
$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;
echo $phone;
echo $state;
В настоящее время выводит как номер телефона, так и состояние. Работает нормально.
Теперь мне нужно знать, является ли значение «Поддерживаемого» ключа Да или Нет, и если да, мне нужно получить все «Продукты». Я немного застрял, потому что мне трудно сделать оператор foreach и затем проверить значение атрибута «ключ».
Спасибо!
Ваш XML неверен. XML-документ всегда нуждается в одном узле элемента документа.
Пример:
<root>
<phone>2125556666</phone>
<State>ny</State>
<Response>
<data key="Supported" value="Yes"/>
...
</data>
</Response>
</root>
Самый простой способ извлечь данные из DOM — это XPath. В PHP это обеспечивается DOMXPath
класс и часть ext/dom
, DOMXPath::evaluate()
позволяет извлекать списки узлов или скалярные значения из документа DOM.
$dom = new DOMDocument;
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$phone = $xpath->evaluate('string(/*/phone)');
$state = $xpath->evaluate('string(/*/State)');
var_dump($phone, $state);
Выход:
string(10) "2125556666"string(2) "ny"
Выражение как /*/phone
выбирает все phone
дочерние узлы элемента внутри элемента документа. string(/*/phone)
бросает первый найденный узел в строку и возвращает его. Если узел не найден, он вернет пустую строку.
Выражение XPath для поддерживаемого статуса немного сложнее. Условия для узлов приведены в []
, Можно сравнить результат непосредственно в XPath. Возвращаемое значение будет логическим.
$supported = $xpath->evaluate('/*/Response/data[@key="Supported"]/@value = "Yes"');
var_dump($supported);
Выход:
bool(true)
Если выражение возвращает список узлов, вы можете повторить его foreach()
,
$nodes = $xpath->evaluate(
'/*/Response/data[@key="WholeProductList"]/data[@key="Product"]/@value'
);
$products = [];
foreach ($nodes as $attributeNode) {
$products[] = $attributeNode->value;
}
var_dump($products);
Выход:
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"}
Это не будет работать «как есть», так как я не знаю, какова реальная структура документа XML, но вкратце вы отображаете узлы XML в XPath, как //root/node/child_node/@attribute
и так далее.
Он также должен иметь некоторый здравый (не нулевой) тип проверки.
$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;
Вы также можете заменить:
$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;
С чем-то вроде (опять же — без полной структуры XML-документа сам путь, вероятно, не совсем правильный):
$phone = $xQuery->query('/phone')->item(0)->nodeValue;
$state = $xQuery->query('/State')->item(0)->nodeValue;