web-dev-qa-db-fra.com

XPath: Obtenir les nœuds où le nœud enfant contient un attribut

Supposons que j'ai le XML suivant:

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>

Je voudrais faire un xpath qui récupère tous les nœuds de livre qui ont un nœud de titre avec un attribut de langue "it".

Ma tentative ressemblait à quelque chose comme ça:

//book[title[@lang='it']]

Mais ça n'a pas marché. Je m'attends à récupérer les nœuds:

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

Des allusions? Merci d'avance.

99
user176872

Essayer

//book[title/@lang = 'it']

Cela se lit:

  • récupère tous les book éléments
    • qui ont au moins un title
      • qui a un attribut lang
        • avec une valeur de "it"

Vous pouvez trouver this utile - c'est un article intitulé "XPath in Five Paragraphs" de Ronald Bourret.

Mais en toute honnêteté, //book[title[@lang='it']] et ce qui précède doit être équivalent, à moins que votre moteur XPath ne présente des "problèmes". Cela pourrait donc être quelque chose dans le code ou l'exemple XML que vous ne nous présentez pas - par exemple, votre exemple est un fragment XML. Se pourrait-il que l'élément racine ait un espace de noms, et vous ne comptez pas pour cela dans votre requête? Et vous nous avez seulement dit que cela ne fonctionnait pas, mais vous ne nous avez pas dit quels résultats vous avez obtenus.

155
lavinio

Des années plus tard, une option utile consisterait à utiliser les axes XPath ( https://www.w3schools.com/xml/xpath_axes.asp ). Plus précisément, vous souhaitez utiliser les axes descendants .

Je crois que cet exemple ferait l'affaire:

//book[descendant::title[@lang='it']]

Cela vous permet de sélectionner tous les éléments book contenant un élément enfant title (quelle que soit sa profondeur imbriquée) contenant une valeur d'attribut de langue égale à 'it'.

Je ne peux pas dire avec certitude si cette réponse est pertinente pour l'année 2009, car je ne suis pas totalement sûr que les XPath Axes existaient à cette époque. Ce que je peux confirmer, c’est qu’ils existent aujourd’hui et que je les ai trouvés extrêmement utiles pour la navigation XPath, et je suis sûr que vous le ferez également.

46
wes.hysell
//book[title[@lang='it']]

est en fait équivalent à

 //book[title/@lang = 'it']

Je l'ai essayé avec vtd-xml, les deux expressions ont craché le même résultat ... quel moteur de traitement xpath avez-vous utilisé? Je suppose qu'il a un problème de conformité. Ci-dessous le code

import com.ximpleware.*;
public class test1 {
  public static void main(String[] s) throws Exception{
      VTDGen vg = new VTDGen();
      if (vg.parseFile("c:/books.xml", true)){
          VTDNav vn = vg.getNav();
          AutoPilot ap = new AutoPilot(vn);
          ap.selectXPath("//book[title[@lang='it']]");
                  //ap.selectXPath("//book[title/@lang='it']");

          int i;
          while((i=ap.evalXPath())!=-1){
              System.out.println("index ==>"+i);
          }
          /*if (vn.endsWith(i, "< test")){
             System.out.println(" good ");  
          }else
              System.out.println(" bad ");*/

      }
  }
}
9
vtd-xml-author

Je pense que votre propre suggestion est correcte, mais le code XML n'est pas tout à fait valide. Si vous exécutez le //book[title[@lang='it']] sur <root>[Your"XML"Here]</root> puis les testeurs xPath en ligne gratuits, tels que l'un ici , trouveront le résultat attendu.

3
Joakim Byg

Essayez d'utiliser cette expression xPath:

//book/title[@lang='it']/..

Cela devrait vous donner tous les nœuds du livre dans "it" lang

0
user1113000