java
  • xpath
  • 2011-08-11 199 views 1 likes 
    1

    我正在使用XPath提取URL128 XML元素的值。即使我在下面的例子中只有一個,也可以有很多。當我在SearchResponse元素上包含xmlns ='http://c1.net.corbis.com/'時,我得到一個空的NodeList,但是當我刪除該名稱空間元素時,它工作正常。有沒有我錯過的配置?XPath解析名稱空間聲明

    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()); 
          } 
    

    回答

    2

    好,長話短說,你需要提供一個NamespaceContextXPath

    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()); 
    } 
    

    這似乎是唯一的方法XPath需要我們實現在這種情況下是getNamespaceURI(String prefix)

    請注意,在這種情況下,「c:URL128」中的實際前綴並不重要 - 您可以輕鬆使用「:URL128」。當你的在你的XML中有多個命名空間時,區分它們變得很重要(如果元素相對較少,則使用Map或一系列if-then-else)。

    如果您不能或不想硬代碼,你可以自己從XML文檔中提取出來,但需要多一點的代碼前綴...

    this blog post詳情請見。下面

    +0

    看到我的替代解決方案... – Adam

    0

    是實現的兩種方式是什麼AlistairIsreal概述:

    如果使用Spring,你可以依靠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

    看到我的替代解決方案... – Adam

    1

    有一個稍微容易的解決了這個,不涉及將硬編碼的URI引用在你的代碼......這簡直是解析設置爲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()); 
    } 
    
    相關問題