使用Xpath提取给定节点的文本和属性
时间:2020-03-06 14:48:31 来源:igfitidea点击:
我正在使用PHP和xpath解析来自API调用的XML结果。
$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'); }
这有效,但是有一种方法可以通过一个查询访问文本和属性吗?如果是的话,一旦执行查询,我们如何获得这些项目?
解决方案
我们可以查询串联吗?
$xpath->query('concat(//a:Books/text(), //a:Books/@DeweyDecimal)', $dom);
XSLT本身就是一种表达式语言,我们可以在表达式中构造所需的返回值的任何特定格式。
环顾四周后,我遇到了这个解决方案。这样,我可以获取元素文本并访问节点的任何属性。
$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'); }
如果我们只是从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表达式,它将同时选择" a:Books"的文本节点及其" DeweyDecimal"属性
// a:Books / text()| // a:Books / @ DeweyDecimal
请注意上面表达式中XPath联合运算符的使用。
另一个注意事项:尽量避免使用" //"缩写,因为它可能导致遍历整个XML文档,因此非常昂贵。建议始终在XML文档的结构已知时使用更具体的XPath表达式(例如,由一系列特定的位置步骤组成)。