为什么在解析XML时会得到空节点值?

4

在解析以下XML时,首先遇到了url-malformed-exception。因此,在代码中,我没有使用xml字符串,而是使用了以下代码

Document doc=dBuilder.parse(newInputSource(newByteArrayInputStream(xmlResponse.getBytes("utf-8"))));

根据这个链接

java.net.MalformedURLException: no protocol

现在我得到的节点值为 null。如何克服这个问题?在 for 循环的代码中,我已经说明了节点为空值的位置。

我正在使用以下代码:

try {
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(xmlResponse.getBytes("utf-8"))));
    //read this - https://dev59.com/2WYr5IYBdhLWcg3wTYcQ
    doc.getDocumentElement().normalize();
    System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
    XPath xPath =  XPathFactory.newInstance().newXPath()
    String expression = "/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product"
    System.out.println(expression)
    NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET)
    System.out.println("the size will be of the node list ${nodeList.getLength()}");
    for (int i = 0; i < nodeList.getLength(); i++) {
            System.out.println(nodeList.item(i).getNodeValue()+"the value coming will be "); // here i am getting value null for each node
    }
} catch (Exception e) {
    e.printStackTrace(System.out);
}

解析XML:

<?xml version="1.0"?>
<GetMatchingProductForIdResponse   xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
  <GetMatchingProductForIdResult Id="H5-9OSH-9NZ7" IdType="SellerSKU" status="Success">
    <Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
    <Product>
      <Identifiers>
        <MarketplaceASIN>
          <MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
          <ASIN>B004FQLAH2</ASIN>
        </MarketplaceASIN>
      </Identifiers>
      <AttributeSets>
        <ns2:ItemAttributes xml:lang="en-US">
          <ns2:Binding>Office Product</ns2:Binding>
          <ns2:Brand>Konica-Minolta</ns2:Brand>
          <ns2:Color>Y</ns2:Color>
          <ns2:CPUSpeed Units="MHz">200</ns2:CPUSpeed>
          <ns2:Department>Printers</ns2:Department>
          <ns2:Feature>Amp Up your Output - The magicolor 3730DN business color laser printer outputs at speeds up to 25 ppm in both color and B&W which means you can keep up in just about any business environment.</ns2:Feature>
          <ns2:Feature>Unparalleled Image Quality - High resolution 2400 (equivalent) x 600 dpi printing for great color and clarity in both images and text.</ns2:Feature>
          <ns2:Feature>Happy Planet, Outstanding Printing - Simitri HD Toner with Biomass allows for outstanding printing with the environment in mind.</ns2:Feature>
          <ns2:Feature>Connect quicker - Why wait? Standard Ethernet and high-speed USB 2.0 gets you connected faster than ever before.Specifications</ns2:Feature>
          <ns2:Feature>Type - Full-Color Laser Printer</ns2:Feature>
          <ns2:ItemDimensions>
            <ns2:Height Units="inches">13.62</ns2:Height>
            <ns2:Length Units="inches">20.47</ns2:Length>
            <ns2:Width Units="inches">16.50</ns2:Width>
            <ns2:Weight Units="pounds">56.22</ns2:Weight>
          </ns2:ItemDimensions>
          <ns2:IsAutographed>false</ns2:IsAutographed>
          <ns2:IsMemorabilia>false</ns2:IsMemorabilia>
          <ns2:Label>Konica</ns2:Label>
          <ns2:ListPrice>
            <ns2:Amount>449.00</ns2:Amount>
            <ns2:CurrencyCode>USD</ns2:CurrencyCode>
          </ns2:ListPrice>
          <ns2:Manufacturer>Konica</ns2:Manufacturer>
          <ns2:Model>A0VD017</ns2:Model>
          <ns2:NumberOfItems>1</ns2:NumberOfItems>
          <ns2:OperatingSystem>Windows XP, Vista, 7</ns2:OperatingSystem>
          <ns2:OperatingSystem>Mac X 10.2.8, 10.6+</ns2:OperatingSystem>
          <ns2:PackageDimensions>
            <ns2:Height Units="inches">19.00</ns2:Height>
            <ns2:Length Units="inches">24.20</ns2:Length>
            <ns2:Width Units="inches">22.00</ns2:Width>
            <ns2:Weight Units="pounds">65.30</ns2:Weight>
          </ns2:PackageDimensions>
          <ns2:PackageQuantity>1</ns2:PackageQuantity>
          <ns2:PartNumber>A0VD017</ns2:PartNumber>
          <ns2:ProductGroup>CE</ns2:ProductGroup>
          <ns2:ProductTypeName>PRINTER</ns2:ProductTypeName>
          <ns2:Publisher>Konica</ns2:Publisher>
          <ns2:SmallImage>
            <ns2:URL>http://ecx.images-amazon.com/images/I/21qN3BU-BHL._SL75_.jpg</ns2:URL>
            <ns2:Height Units="pixels">75</ns2:Height>
            <ns2:Width Units="pixels">75</ns2:Width>
          </ns2:SmallImage>
          <ns2:Studio>Konica</ns2:Studio>
          <ns2:Title>Konica Minolta Magicolor 3730DN Color Laser Printer 24PPM 2400X600DPI ENET USB 2.0</ns2:Title>
        </ns2:ItemAttributes>
      </AttributeSets>
      <Relationships/>
      <SalesRankings/>
    </Product>
    </Products>
  </GetMatchingProductForIdResult>
  <ResponseMetadata>
    <RequestId>0b508338-3afe-4178-adc4-60c9c8448987</RequestId>
  </ResponseMetadata>
</GetMatchingProductForIdResponse>
1个回答

16

getNodeValue 方法在 DOM 中被定义为对于元素节点始终返回 null(有关详细信息,请参见org.w3c.dom.Node 的 JavaDoc 页面顶部的表格)。如果您想要获取元素内部的文本,则应改用 getTextContent()

您在此答案的评论中添加了第二个问题,询问如何使用XPath搜索具有名称空间前缀例如 ns2: 的节点。XPath 1.0 处理命名空间的方式是,未命名的名称始终引用不属于命名空间的节点,如果您想要引用有命名空间的节点,则必须提供命名空间 URI 到前缀的绑定(在 javax.xml.xpath 中是 NamespaceContext 的工作),然后在表达式中使用这些前缀。在表达式中使用的前缀不必与原始文档使用的前缀相同,只要它们将绑定到正确的 URI。

因此,您最初使用的 XPath 是:

/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product

在你的文档中,GetMatchingProductForIdResponse等元素处于命名空间中,因此实际上不应该匹配任何内容,但是由于DocumentBuilderFactory默认情况下不具有命名空间感知性,所以你得到了它。 在这里正确的做法是使用具有命名空间感知性的解析器,并向XPath引擎提供适当的命名空间上下文。 不幸的是,在核心Java库中没有可用的NamespaceContext默认实现,但是如果您不想自己编写,则Spring提供了一个方便的SimpleNamespaceContext实现可供使用。

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true); // parse with namespaces
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(xmlResponse.getBytes("utf-8"))));
doc.getDocumentElement().normalize();

XPath xPath =  XPathFactory.newInstance().newXPath();
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
xPath.setNamespaceContext(nsCtx);
nsCtx.bindNamespaceUri("prod", "http://mws.amazonservices.com/schema/Products/2011-10-01");
nsCtx.bindNamespaceUri("ns2", "http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd");
String expression = "/prod:GetMatchingProductForIdResponse/prod:GetMatchingProductForIdResult/prod:Products/prod:Product‌​/prod:AttributeSets/ns2:ItemAttributes/ns2:Binding";
// ...

字符串表达式 = "/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/ns2:ItemAttributes/ns2:Binding" 用此代码计算 NodeList 直到 ns2:binding NodeList nodeList = xPath.compile(expression).evaluate(doc,XPathConstants.NODESET),节点列表的大小为零,为什么?我该如何获取节点ns2:binding的文本内容? - Deepak
@Ian Roberts先生,我明白了,我必须从标签名称中删除命名空间,当然您已经在下面回答了,以下是链接:http://stackoverflow.com/questions/13623505/xml-parser-for-colon-separated-tags - Deepak
@Deepak 我已经添加了一些关于如何处理javax.xml.xpath中命名空间的详细信息。 - Ian Roberts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接