Извлекает как текст, так и атрибут данного узла с помощью Xpath
Вопрос
Я анализирую XML-результаты вызова API с использованием PHP и xpath.
$dom = new DOMDocument();
$dom->loadXML($response->getBody());
$xpath = new DOMXPath($dom);
$xpath->registerNamespace("a", "http://www.example.com");
$hrefs = $xpath->query('//a:Books/text()', $dom);
for ($i = 0; $i < $hrefs->length; $i++) {
$arrBookTitle[$i] = $hrefs->item($i)->data;
}
$hrefs = $xpath->query('//a:Books', $dom);
for ($i = 0; $i < $hrefs->length; $i++) {
$arrBookDewey[$i] = $hrefs->item($i)->getAttribute('DeweyDecimal');
}
Это работает, но есть ли способ, которым я могу получить доступ как к тексту, так и к атрибуту из одного запроса?И если да, то как вы получаете доступ к этим элементам после выполнения запроса?
Решение
Немного осмотревшись, я наткнулся на это решение.Таким образом, я могу получить текст элемента и получить доступ к любым атрибутам узла.
$hrefs = $xpath->query('//a:Books', $dom);
for ($i = 0; $i < $hrefs->length; $i++) {
$arrBookTitle[$i] = $hrefs->item($i)->nodeValue;
$arrBookDewey[$i] = $hrefs->item($i)->getAttribute('DeweyDecimal');
}
Другие советы
Одно единственное выражение XPath, которое будет выбирать как текстовые узлы "a: Books", так и их атрибут "DeweyDecimal", является следующим
//a:Books/text() | //a:Books/@DeweyDecimal
Обратите внимание использование оператора объединения XPath в приведенном выше выражении.
Еще одна записка:старайтесь избегать использования аббревиатуры "//", поскольку это может привести к обходу всего XML-документа и, следовательно, обойдется очень дорого.Рекомендуется использовать более конкретное выражение XPath (например, состоящее из цепочки определенных шагов определения местоположения) всегда, когда известна структура XML-документа.
Если вы просто извлекаете значения из своего XML-документа, SimpleXML возможно, это более компактное, быстрое и дружественное к памяти решение:
$xml=simplexml_load_string($response->getBody());
$xml->registerXPathNamespace('a', 'http://www.example.com');
$books=$xml->xpath('//a:Books');
foreach ($books as $i => $book) {
$arrBookTitle[$i]=(string)$book;
$arrBookDewey[$i]=$book['DeweyDecimal'];
}
Не могли бы вы запросить конкатенацию?
$xpath->query('concat(//a:Books/text(), //a:Books/@DeweyDecimal)', $dom);
XSLT сам по себе является языком выражений, и вы можете создать любой конкретный формат возвращаемого значения, который вы хотите, из выражения.