124 votes

Obtenir les noeuds dont le noeud 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 noeuds de livres qui ont un noeud de titre avec un attribut de langue de "it".

Ma tentative ressemblait à ceci :

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

Mais ça n'a pas marché. J'espère récupérer les noeuds :

<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 conseils ?

189voto

lavinio Points 12592

Essayez

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

C'est écrit :

  • obtenir tous book elementos
    • qui ont au moins un title
      • qui a un attribut lang
        • avec une valeur de "it"

Vous pouvez trouver ce utile - il s'agit d'un article intitulé "XPath en cinq paragraphes" par Ronald Bourret.

Mais en toute honnêteté, //book[title[@lang='it']] et ce qui précède devrait être équivalent, à moins que votre moteur XPath ait des "problèmes". Il pourrait donc s'agir de quelque chose dans le code ou l'échantillon XML que vous ne nous montrez pas - par exemple, votre échantillon est un fragment XML. Il se pourrait que l'élément Root ait un espace de nom et que vous ne le preniez pas en compte 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.

59voto

wes.hysell Points 140

Des années plus tard, mais une option utile serait d'utiliser les XPath Axes ( https://www.w3schools.com/xml/xpath_axes.asp ). Plus précisément, vous cherchez à utiliser le descendants axes.

Je pense que cet exemple ferait l'affaire :

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

Cela vous permet de sélectionner tous les book qui contiennent un élément enfant title (quelle que soit la profondeur de son imbrication) contenant une valeur d'attribut de langue égale à "it".

Je ne peux pas dire avec certitude si cette réponse est pertinente ou non pour l'année 2009 car je ne suis pas certain à 100% que les axes XPath 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 dans la navigation XPath, et je suis sûr que vous en ferez autant.

14voto

vtd-xml-author Points 891
//book[title[@lang='it']]

est en fait équivalent à

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

J'ai essayé en utilisant vtd-xml, les deux expressions ont donné le même résultat... quel moteur de traitement xpath avez-vous utilisé ? Je suppose qu'il y a un problème de conformité Voici 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 ");*/

      }
  }
}

4voto

Joakim Byg Points 11

Je pense que votre propre suggestion est correcte, cependant le xml n'est pas tout à fait valide. Si vous exécutez le //book[title[@lang='it']] en <root>[Your"XML"Here]</root> alors les testeurs gratuits en ligne de xPath tels que celui ici trouvera le résultat attendu.

2voto

user1113000 Points 21

Essayez d'utiliser cette expression xPath :

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

Cela devrait vous donner tous les nœuds du livre dans la langue "it".

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