java
  • xpath
  • 2011-08-11 153 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()); 
    } 
    
    相关问题