2010-11-02 6 views
4

Dire que j'ai le fichier XML suivant:parsing XML en utilisant XPath en Java

<?xml version="1.0" encoding="utf-8"?> 
<venues> 
    <group type="Nearby"> 
    <venue> 
     <id>222307</id> 
     <name>Union Chapel</name> 
     <primarycategory> 
     <id>78967</id> 
     <fullpathname>Arts &amp; Entertainment:Music Venue</fullpathname> 
     <nodename>Music Venue</nodename> 
     <iconurl>http://foursquare.com/img/categories/arts_entertainment/musicvenue.png</iconurl> 
     </primarycategory> 
     <address>Compton Ave</address> 
     <city>Islington</city> 
     <state>Greater London</state> 
     <zip>N1 2XD</zip> 
     <verified>false</verified> 
     <geolat>51.5439732</geolat> 
     <geolong>-0.1020908</geolong> 
     <stats> 
     <herenow>0</herenow> 
     </stats> 
     <phone>02073594019</phone> 
     <distance>33</distance> 
    </venue> 

.............

et mon code est le suivant:

XPathFactory factory = XPathFactory.newInstance(); 
    XPath xpath = factory.newXPath(); 
    XPathExpression expr = xpath.compile("//venue/*"); 

    Object result = expr.evaluate(document, XPathConstants.NODESET); 
    NodeList nodes = (NodeList) result; 
    //System.out.println(nodes.getLength()); 

    Venue ven = new Venue(); 

    for (int i = 0; i < nodes.getLength(); i++) { 
     String nodeName = nodes.item(i).getNodeName(); 
     String nodeValue = nodes.item(i).getNodeValue(); 


     if (nodeName.equals("id")){ 
      ven = new Venue(); 
      if (nodeValue != null) 
       ven.id = Integer.parseInt(nodeValue); 
      System.out.println(ven.id); 
     } 

     if (nodeName.equals("name")){ 
      ven.name = nodeValue; 
      System.out.println(ven.name); 
     } 

     if (nodeName.equals("address")){ 
      ven.address = nodeValue; 
      System.out.println(ven.address); 
     } 

Comment puis-je faire tout cela dans une boucle pour l'efficacité? Dans le cas contraire pour chaque attribut dans le xml que je veux extraire Je dois créer une boucle pour chacun d'entre eux

Répondre

6

Si vous utilisez ce que votre XPath:

//venue/* 

Vous obtiendrez tous les enfants nœuds de lieu. Vous pouvez ensuite itérer sur ceci et faire un gros sinon sur le nom du noeud et les assigner au besoin.

Comme ceci:

XPathFactory factory = XPathFactory.newInstance(); 
XPath xpath = factory.newXPath(); 
XPathExpression expr = xpath.compile("//venue/*"); 

Object result = expr.evaluate(document, XPathConstants.NODESET); 
NodeList nodes = (NodeList) result; 
for (int i = 0; i < nodes.getLength(); i++) { 
      Node node = nodes.item(i); 
      String nodeName = node.getNodeName(); 
      String nodeValue = node.getChildNodes().item(0).getNodeValue(); 


      if(nodeName.equals("name")) { 
         name = nodeValue; 
      } 
      else if(nodeName.equals("address")) { 
         address = nodeValue; 
      } // ... the rest goes here 
} 

Si vous ne voulez pas itérer sur tous les éléments de l'enfant que vous pourriez faire quelque chose comme ceci:

XPathExpression expr = xpath.compile("//venue"); 

    Object result = expr.evaluate(document, XPathConstants.NODESET); 
    NodeList nodes = (NodeList)result; 
    for(int i = 0; i < nodes.getLength(); i++) { 
     Node node = nodes.item(i); 
     NodeList venueChildNodes = node.getChildNodes(); 

     String id = venueChildNodes.item(1).getChildNodes().item(0).getNodeValue(); 
     System.out.println("id: " + id); 

     String name = venueChildNodes.item(3).getChildNodes().item(0).getNodeValue(); 
     System.out.println("name: " + name); 

     String address = venueChildNodes.item(7).getChildNodes().item(0).getNodeValue(); 
     System.out.println("address: " + address); 
    } 

où vous obtenez tous les nœuds du lieu et carte alors il est enfants. Cependant, cette approche nécessiterait une structure xml assez cohérente. Bien que, quelque chose comme ça me semble plus sûr de:

XPathExpression expr = xpath.compile("//venue"); 

    Object result = expr.evaluate(document, XPathConstants.NODESET); 
    NodeList nodes = (NodeList)result; 
    for(int i = 0; i < nodes.getLength(); i++) { 
     Node node = nodes.item(i); 
     NodeList venueChildNodes = node.getChildNodes(); 

     String address = null; 
     String name = null; 

     for(int j = 0; j < venueChildNodes.getLength(); j++) { 
      Node item = venueChildNodes.item(j); 
      String nodeName = item.getNodeName(); 

      if (nodeName.equals("address")) { 
       address = item.getChildNodes().item(0).getNodeValue(); 
      } 

      if (nodeName.equals("name")) { 
       name = item.getChildNodes().item(0).getNodeValue(); 
      } 
     } 

     System.out.println("address: " + address); 
     System.out.println("name: " + name); 
    } 
+0

oh ça ne fait rien, j'ai corrigé le code et ça marche – aherlambang

+0

Si vous faites beaucoup de xpath, je vous recommande vivement d'obtenir sketchpath. C'est un outil gratuit qui vaut la peine d'utiliser IMHO (il existe une version gratuite, mais on dirait qu'ils poussent maintenant une version pro). – javamonkey79

+0

pourquoi est-ce que je reçois 120 comme les nodesLength, alors qu'il n'y a que 10 lieux ...? J'ai une classe appelée lieu et je veux stocker cette information dans ces classes – aherlambang

4

Vous pouvez les combiner comme:

//venue/address/text()|//venue/name/text() 

Cela renverra les noeuds dans l'ordre du document et vous pouvez simplement itérer sur eux.