DomDocument et Domxpath sont deux outils très puissants lors de l'utilisation de PHP pour traiter les données XML. Surtout lorsque des requêtes XML complexes sont nécessaires, l'utilisation des espaces de noms et des expressions XPATH peut considérablement améliorer la flexibilité et la précision. Cet article présentera comment combiner la méthode RegisterXPathNamespace et la fonction XPATH personnalisée pour étendre et améliorer vos capacités de requête XML.
Dans de nombreux documents XML, les éléments et les attributs ont généralement des préfixes d'espace de noms. Par exemple:
<span><span><span class="hljs-tag"><<span class="hljs-name">root</span></span></span><span> </span><span><span class="hljs-attr">xmlns:h</span></span><span>=</span><span><span class="hljs-string">"http://www.w3.org/TR/html4/"</span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:table</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:tr</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:td</span></span></span><span>>Apples</span><span><span class="hljs-tag"></<span class="hljs-name">h:td</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:td</span></span></span><span>>Bananas</span><span><span class="hljs-tag"></<span class="hljs-name">h:td</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">h:tr</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">h:table</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">root</span></span></span><span>>
</span></span>
Pour interroger correctement les nœuds tels que <h: td> , l'expression XPath doit connaître l'espace de noms URI correspondant au préfixe h . C'est à ce moment que RegisterXpathNamespace est utile.
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMDocument</span></span><span>();
</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">loadXML</span></span><span>(</span><span><span class="hljs-variable">$yourXmlString</span></span><span>);
</span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">registerNamespace</span></span><span>(</span><span><span class="hljs-string">"h"</span></span><span>, </span><span><span class="hljs-string">"http://www.w3.org/TR/html4/"</span></span><span>);
</span><span><span class="hljs-variable">$tds</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"//h:td"</span></span><span>);
</span></span>
Bien que la langue XPath elle-même soit puissante, dans certains scénarios de logique commerciale, les fonctions XPATH intégrées peuvent ne pas répondre aux besoins. Par exemple, nous pourrions vouloir utiliser une fonction pour déterminer si la valeur d'un élément apparaît dans une base de données ou un tableau, ou pour effectuer un traitement de chaîne plus complexe.
PHP native ne prend pas en charge l'injection de fonctions personnalisées dans XPATH, mais peut être partiellement simulé par des solutions de contournement, telles que l'appel des fonctions PHP pour implémenter la logique lors de la traversée des résultats de la requête ou de la combinaison de LiBXML et XSLTProcessor .
Mais il est plus courant d'enregistrer l'espace de noms et de prétraiter le XML avant d'utiliser la requête XPATH, puis de faire fonctionner le nœud avec des fonctions personnalisées.
Supposons que vous ayez le document XML suivant contenant plusieurs nœuds <élément> avec des espaces de noms:
<span><span><span class="hljs-tag"><<span class="hljs-name">catalog</span></span></span><span> </span><span><span class="hljs-attr">xmlns:bk</span></span><span>=</span><span><span class="hljs-string">"http://example.com/book"</span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:item</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:title</span></span></span><span>>PHP programmation</span><span><span class="hljs-tag"></<span class="hljs-name">bk:title</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:price</span></span></span><span>>45</span><span><span class="hljs-tag"></<span class="hljs-name">bk:price</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">bk:item</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:item</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:title</span></span></span><span>>Java programmation</span><span><span class="hljs-tag"></<span class="hljs-name">bk:title</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">bk:price</span></span></span><span>>55</span><span><span class="hljs-tag"></<span class="hljs-name">bk:price</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">bk:item</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">catalog</span></span></span><span>>
</span></span>
Vous souhaitez interroger tous les titres de livre pour le prix inférieur à 50 yuans. XPath lui-même prend en charge les comparaisons numériques:
<span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">registerNamespace</span></span><span>(</span><span><span class="hljs-string">"bk"</span></span><span>, </span><span><span class="hljs-string">"http://example.com/book"</span></span><span>);
</span><span><span class="hljs-variable">$nodes</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"//bk:item[bk:price < 50]/bk:title"</span></span><span>);
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$nodes</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>->nodeValue . </span><span><span class="hljs-string">"\n"</span></span><span>;
}
</span></span>
Si vous souhaitez implémenter une logique plus complexe (comme un prix inférieur à 50 et que le titre contient "PHP"), vous pouvez combiner plusieurs conditions XPath:
<span><span><span class="hljs-variable">$nodes</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"//bk:item[bk:price < 50 and contains(bk:title, 'PHP')]/bk:title"</span></span><span>);
</span></span>
Cependant, si la logique est plus compliquée, telle que "garder uniquement les nœuds avec le titre contenant n'importe quel mot dans le tableau des mots clés", vous devez filtrer les résultats avec une fonction personnalisée après la requête:
<span><span><span class="hljs-variable">$keywords</span></span><span> = [</span><span><span class="hljs-string">'PHP'</span></span><span>, </span><span><span class="hljs-string">'MySQL'</span></span><span>, </span><span><span class="hljs-string">'Laravel'</span></span><span>];
</span><span><span class="hljs-variable">$nodes</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"//bk:item/bk:title"</span></span><span>);
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$nodes</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>) {
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$keywords</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$word</span></span><span>) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">stripos</span></span><span>(</span><span><span class="hljs-variable">$node</span></span><span>->nodeValue, </span><span><span class="hljs-variable">$word</span></span><span>) !== </span><span><span class="hljs-literal">false</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>->nodeValue . </span><span><span class="hljs-string">"\n"</span></span><span>;
</span><span><span class="hljs-keyword">break</span></span><span>;
}
}
}
</span></span>
Bien qu'il s'agisse d'un traitement logique en dehors du résultat de la requête XPATH, il combine essentiellement les capacités de requête XPath et la logique personnalisée PHP.
Si vous devez réellement intégrer les fonctions PHP dans la logique XPath, envisagez de combiner les fonctions d'extension XSLTProcessor et PHP. Par exemple, le jugement logique est implémenté en enregistrant des fonctions d'extension (telles que PHP: FunctionString ('Your_Function') ) - Il s'agit d'une utilisation d'ordre supérieur, et nécessite l'activation de l'extension XSL en PHP et la prête d'attention à la sécurité.