Estrarre sia il testo che l'attributo di un dato nodo usando Xpath
Domanda
Sto analizzando i risultati XML da una chiamata API usando PHP e 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');
}
Funziona ma c'è un modo per accedere sia al testo che all'attributo da una query? E se sì, come si arriva a questi elementi una volta eseguita la query?
Soluzione
Dopo aver guardato in giro mi sono imbattuto in questa soluzione. In questo modo posso ottenere il testo dell'elemento e accedere a qualsiasi attributo del nodo.
$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');
}
Altri suggerimenti
Un'unica espressione XPath che selezionerà entrambi i nodi di testo di " a: Books " e il loro " DeweyDecimal " attributo, è il seguente
// a: Libri / testo () | // a: Libri / @ DeweyDecimal
Nota l'uso dell'operatore sindacale XPath nell'espressione sopra.
Un'altra nota : cerca di evitare di utilizzare il " // " abbreviazione in quanto potrebbe far attraversare l'intero documento XML e quindi è molto costoso. Si consiglia di utilizzare un'espressione XPath più specifica (ad esempio costituita da una catena di passaggi di posizione specifici) sempre quando è nota la struttura del documento XML.
Se stai solo recuperando valori dal tuo documento XML, SimpleXML potrebbe essere la soluzione più snella, più veloce e più adatta alla memoria:
$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'];
}
Potresti richiedere la concatenazione?
$xpath->query('concat(//a:Books/text(), //a:Books/@DeweyDecimal)', $dom);
XSLT è un linguaggio di espressione in sé e puoi creare qualsiasi formato specifico di valore di ritorno desideri all'interno dell'espressione.