Problème avec Xpath et xmlns par défaut

Papi II
Invité n'ayant pas de compte PHPfrance

26 nov. 2007, 23:19

Bonsoir à tous,

j'ai un petit soucis, si si. Quand j'utilise un DOM sur un flux XML ayant un "name space" par défaut, je ne récupère plus loin.

Par exemple: si votre flux XML est :
<nvd xmlns="http://nvd.nist.gov/feeds/cve/1.2">
 <entry type="CVE" name="CVE-2007-0001" seq="2007-0001" published="2007-03-02">
 ...
 </entry>
</nvd>

Dans mon script :
...
$pDocumentXML = new DOMDocument( "1.0", "UTF-8" ) ;
$pDocumentXML->preserveWhiteSpace = false ;

$pDocumentXML->load( "nvdcve-2007.xml" );

$Requeteur = new DOMXPath( $pDocumentXML );
$Noeuds = $Requeteur->query( "/nvd/entry" );

if ( $Noeuds->length > 0 ) {
	print "Il existe <b>" . $Noeuds->length . " occurrence(s)</b> répondant aux critères de recherche<br/><br/>\n" ;
} else {
	print "Il n'existe pas d'occurrence répondant aux critères de recherche<br/><br/>\n" ;
}
...
Et bien il me dit systématiquement qu'il n'y a pas d'occurrence. Or, dès que j'enlève l'attribut "xmlns", cela fonctionne.

Donc, comment faire pour que le DOM PHP tienne compte des espaces de nom par défaut ?

Par avance merci.

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

26 nov. 2007, 23:43

Modération :
Papi II, afin d'améliorer la lisibilité de ton message,
pense à utiliser les balises [code] ou [php] (selon le langage utilisé).

Elles sont disponibles au-dessus de la zone de saisie de ton message
lorsque tu postes un nouveau message.

Des indications sont disponibles sur la manière de mettre en forme vos messages dans la FAQ

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 nov. 2007, 06:52

Si tu ne précises pas de namespace dans ton XPath, il ne cherchera que des éléments sans namespaces.

Je ne crois pas qu'il existe un moyen de spécifier un namespace par défaut pour XPath, donc il te faudra créer un préfixe pour ta requête. Par exemple
$Requeteur->registerNamespace('cve', 'http://nvd.nist.gov/feeds/cve/1.2');
$Noeuds = $Requeteur->query( "/cve:nvd/cve:entry" );
J'ai déplacé le sujet dans le forum approprié, à l'avenir prends quelques secondes supplémentaires avant de décider où poster, merci.

Papy II
Invité n'ayant pas de compte PHPfrance

30 nov. 2007, 16:33

Bonjour à tous et merci pour les réponses précédentes.

Effectivement, en utilisant la méthode xpath->registerNamepace, on arrive à récupérer les bonnes informations dans le flux XML.

Cependant, l'exercice que je n'arrive pas à résoudre est le suivant : Ci-dessous la requete Xpath qui fonctionne quand je supprime la notion de "nameSpace" :
$Xpath = new DOMXpath( $DOM_Vulnerabilites ) ;
$Requete = "/nvd/entry[@severity = 'High']/desc[contains(descript, 'Outlook')]/descript" ;
$Entrees = $Xpath->query( $Requete ) ;
Ci-dessous, celle qui ne fonctionne pas quand j'utilise la notion de "nameSpace" :
$Xpath = new DOMXpath( $DOM_Vulnerabilites ) ;
$Xpath->registerNamespace( "rns", "http://nvd.nist.gov/feeds/cve/1.2" );
$Requete = "//rns:nvd//rns:entry[@severity = 'High']//rns:desc[contains(/rns:descript, 'Outlook')]//rns:descript" ;
$Entrees = $Xpath->query( $Requete ) ;
J'ai essayé différentes variantes. Ce qui bloque, c'est l'utilisation de la fonction

Code : Tout sélectionner

contains
. Effectivement quand j'enlève cette précision, je trouve plusieurs occurrences rattachées à la notion

Code : Tout sélectionner

@severity = 'High'
dans mon flux. Ce qui démontre que la première partie de la requête est bonne et donc que la notion de namespace est acquise.
Mais alors, comment faire pour faire fonctionner l'appel à des fonctions.

Par avance merci.

Papy II
Invité n'ayant pas de compte PHPfrance

30 nov. 2007, 17:11

Je viens de comprendre, j'avais mal lu un exemple d'un autre forum et pire j'avais mal lu la réponse qui m'a été faite sur ce même forum. Quand on utilise un nameSpace, on est pas obligé de le préfixer par un "/".
Donc quand on code :
$Xpath = new DOMXpath( $DOM_Vulnerabilites ) ;
$Xpath->registerNamespace( "rns", "http://nvd.nist.gov/feeds/cve/1.2" );
On doit utiliser le nameSpace comme ci-dessous :
$Requete = "/rns:nvd/rns:entry[@severity = 'High']/rns:desc[contains(rns:descript, 'Outlook')]/rns:descript" ;
$Entrees = $Xpath->query( $Requete ) ;
Et non pas comme je l'avais écrit plus tôt :
$Requete = "//rns:nvd//rns:entry[@severity = 'High']//rns:desc[contains(/rns:descript, 'Outlook')]//rns:descript" ;
$Entrees = $Xpath->query( $Requete ) ;
Et là, forcément cela fonctionne beaucoup mieux.

En tout cas, merci à tous.

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

30 nov. 2007, 17:28

Modération :
Puisque ta question est résolue, j'ajoute le tag [Résolu]
pour indiquer aux personnes qui voudront consulter ce sujet qu'il contient une solution.

Tu peux réaliser cette opération toi-même
en cliquant sur le bouton Image qui s'affiche en haut à gauche de ce sujet
si tu as posté le 1er message en tant que membre (inscrit et identifié).

Alors... inscris-toi !!! ;)

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute