2011-08-11 6 views
1

J'utilise XPath pour extraire uniquement les valeurs de l'élément XML URL128. Il peut y avoir beaucoup de ceux-ci même si j'en ai juste un dans l'exemple ci-dessous. Lorsque j'inclus xmlns = 'http: //c1.net.corbis.com/' sur l'élément SearchResponse, j'obtiens une NodeList vide, mais quand je supprime cet élément de l'espace de noms cela fonctionne très bien. Y a-t-il une configuration qui me manque?XPath Analyse des déclarations d'espace de noms

String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>"; 
      InputSource source = new InputSource(new StringReader(xmlData)); 

      XPath xPath = XPathFactory.newInstance().newXPath(); 
      NodeList list = null; 
      try { 
       list = (NodeList) xPath.evaluate("//URL128/@Value", source, XPathConstants.NODESET); 
      } catch (Exception ex) { 
       System.out.println(ex.getMessage()); 
      } 
      for (int i = 0; i < list.getLength(); i++) { 
       System.out.println(list.item(i).getTextContent()); 
      } 

Répondre

2

Eh bien, longue histoire courte, vous devez fournir un NamespaceContext à votre XPath:

final XPath xPath = XPathFactory.newInstance().newXPath(); 
xPath.setNamespaceContext(new NamespaceContext() { 
    @Override 
    public Iterator<String> getPrefixes(final String namespaceURI) { 
     return null; 
    } 
    @Override 
    public String getPrefix(final String namespaceURI) { 
     return null; 
    } 
    @Override 
    public String getNamespaceURI(final String prefix) { 
     return "http://c1.net.corbis.com/"; 
    } 
}); 
final NodeList list = (NodeList) xPath.evaluate("//c:URL128/@Value", source, XPathConstants.NODESET); 
for (int i = 0; i < list.getLength(); i++) { 
    System.out.println(list.item(i).getTextContent()); 
} 

Il semble que la seule méthode XPath nous oblige à mettre en œuvre dans ce cas est getNamespaceURI(String prefix). Notez que le préfixe actuel dans "c: URL128" n'a pas vraiment d'importance dans ce cas-là, vous pouvez tout simplement utiliser ": URL128". Lorsque vous avez plusieurs espaces de noms dans votre fichier XML, il devient important de distinguer entre eux (en utilisant un Map ou une série de if-then-else si relativement peu d'éléments).

Si vous ne pouvez pas ou ne veulent pas coder en dur les préfixes que vous pouvez les extraire vous à partir du document XML, mais qui nécessite un peu plus de code ...

Voir aussi this blog post pour plus de détails.

+0

Voir ma solution de rechange à cette ... – Adam

0

ci-dessous sont deux façons de mettre en œuvre ce que AlistairIsreal: décrites

si vous utilisez le printemps, vous pouvez compter sur l'interface org.springframework.util.xml.SimpleNamespaceContext.

InputSource source = new InputSource(new StringReader(unescaped)); 

      XPath xPath = XPathFactory.newInstance().newXPath(); 
      NodeList list = null; 
      try 
      { 
       SimpleNamespaceContext nsCtx = new SimpleNamespaceContext(); 
       nsCtx.bindNamespaceUri("ns", "http://c1.net.corbis.com/"); 
       xPath.setNamespaceContext(nsCtx); 
       list = (NodeList) xPath.evaluate("//ns:URL128/@Value", source, XPathConstants.NODESET); 
      } catch (Exception ex) 
      { 
       System.out.println(ex.getMessage()); 
      } 
      for (int i = 0; i < list.getLength(); i++) 
      { 
       System.out.println(list.item(i).getTextContent()); 
      } 
+0

Voir ma solution alternative à cette ... – Adam

1

Il y a une solution à cela, un peu plus facile qui ne comporte pas de placer des références URI définitivement dans votre code ... analyser simplement le document avec l'espace de noms attribut conscient défini sur false ...

String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>"; 
InputSource source = new InputSource(new StringReader(xmlData)); 

// create doc instance instead of passing source straight to XPath... 
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setNamespaceAware(false); // must be false 
DocumentBuilder builder = factory.newDocumentBuilder(); 
final Document doc = builder.parse(source); 

XPath xPath = XPathFactory.newInstance().newXPath(); 

// use doc instead 
NodeList list = (NodeList) xPath.evaluate("//URL128/@Value", doc, 
     XPathConstants.NODESET); 

for (int i = 0; i < list.getLength(); i++) { 
    System.out.println(list.item(i).getTextContent()); 
}