76 votes

XPath - Obtenir un nœud sans enfant de type spécifique

XML: /A/B ou /A

Je souhaite obtenir tous les nœuds A n'ayant aucun enfant B .

J'ai essayé

 /A[not(B)]  
/A[not(exists(B))]
 

sans succès

Je préfère une solution avec la syntaxe /*[local-name()="A" and .... ] , si possible. Des idées qui fonctionnent?

Clarification. Le xml ressemble à:

 <WhatEver>
  <A>
    <B></B>
  </A>
</WhatEver> 
 

ou

 <WhatEver>
  <A></A>
</WhatEver>
 

59voto

alamar Points 6376

Peut-être que *[local-name() = 'A' and not(descendants::*[local-name() = 'B'])] ?

En outre, il ne doit y avoir qu'un seul élément racine. Par conséquent, pour /A[...] vous récupérez tout votre code XML ou aucun. Peut-être que //A[not(B)] ou /*/A[not(B)] ?

Je ne comprends pas vraiment pourquoi /A[not(B)] ne fonctionne pas pour vous.

 ~/xml% xmllint ab.xml
<?xml version="1.0"?>
<root>
    <A id="1">
            <B/>
    </A>
    <A id="2">
    </A>
    <A id="3">
            <B/>
            <B/>
    </A>
    <A id="4"/>
</root>
~/xml% xpath ab.xml '/root/A[not(B)]'
Found 2 nodes:
-- NODE --
<A id="2">
    </A>
-- NODE --
<A id="4" />
 

25voto

Сергій Points 1077

Essayez ceci "/A[not(.//B)]" ou ce "/A[not(./B)]".

12voto

AnthonyWJones Points 122520

Le premier / fait que XPath commence à la racine du document, je doute que ce soit ce que vous vouliez.

Peut-être que vous vouliez dire // A [pas (B)] qui trouverait tous les nœuds A du document à n’importe quel niveau n’ayant pas d’enfant B direct.

Ou peut-être êtes-vous déjà à un nœud contenant des nœuds A, auquel cas vous souhaitez simplement A [pas (B)] en tant que XPath.

3voto

Rashmi Pandit Points 9341

Si vous essayez d’obtenir A n’importe où dans la hiérarchie à partir de la racine, cela fonctionne (pour xslt 1.0 ainsi que 2.0 au cas où il serait utilisé dans xslt)

 //descendant-or-self::node()[local-name(.) = 'a' and not(count(b))]
 

OU vous pouvez aussi faire

 //descendant-or-self::node()[local-name(.) = 'a' and not(b)]
 

OU aussi

 //descendant-or-self::node()[local-name(.) = 'a' and not(child::b)]
 

Il n'y a pas moyen de faire la même chose dans xslt.

Remarque: les XPath sont sensibles à la casse. Par conséquent, si vos noms de nœud sont différents (ce qui, j'en suis sûr, n'utilisera pas A, B), assurez-vous que la casse correspond.

3voto

Cobaia Points 349

Utilisez ceci:

 /*[local-name()='A' and not(descendant::*[local-name()='B'])]
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X