【问题标题】:Java XML - Node Name and Value retrieval not as expectedJava XML - 节点名称和值检索不符合预期
【发布时间】:2021-08-26 15:47:47
【问题描述】:

使用以下示例解析 XML 文件。 能够让它与从不同地方采集的样本一起工作,但它并没有向我解释为什么以下失败是这篇文章的目标。

这是正在执行的代码。

import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XMLQuestions   
{

    public static void main(String argv[]) 
    {
       try 
       {
        String filepath = "c:\\Downloads\\DummyData.xml";

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(filepath);
        doc.setXmlStandalone(true);

        NodeList allDeliveryLocations = doc.getElementsByTagName("DeliveryLocations");
        for(int j=0; j < allDeliveryLocations.getLength();j++)
        {
            Element deliveryLocationElement = (Element) allDeliveryLocations.item(j);
            Node deliveryLocationNode = (Node) allDeliveryLocations.item(j);

            System.out.println("Get Element & Node Name");
            System.out.println("     deliveryLocationElement : " + deliveryLocationElement.getNodeName());
            System.out.println("     deliveryLocationNode    : " + deliveryLocationNode.getNodeName());
            System.out.println("");
            
            System.out.println("GetFirstChild()");
            Node deliveryLocationChild = deliveryLocationNode.getFirstChild();
            System.out.println("     Node Name  : " + deliveryLocationChild.getNodeName());
            System.out.println("     Node Value : " + deliveryLocationChild.getNodeValue() );
            System.out.println("");

        System.out.println("GetNextSibling()");
        deliveryLocationChild = deliveryLocationChild.getNextSibling();
        System.out.println("     Node Name  : " + deliveryLocationChild.getNodeName());
        System.out.println("     Node Value : " + deliveryLocationChild.getNodeValue());
        System.out.println("");
            
       }
        System.out.println("Done");
        
       } catch (ParserConfigurationException pce) {
        pce.printStackTrace();
       } 
       catch (IOException ioe) {
        ioe.printStackTrace();
       } catch (SAXException sae) {
        sae.printStackTrace();
       }
    }
}

用于测试的示例 XML。

<?xml version="1.0" encoding="UTF-8"?>
<AllStorage>
  <NorthAmerica>
      <EastCoast>
        <DeliveryLocations>
        <Location>North East </Location>
          <Item1>Full</Item1>
          <Item2>Empty</Item2>
          <Item3 attr1="1" attr2="2" />
          <Item4 istransferable="true">
            <States>
              <State>
                <NewYork>
                  <UpTown>
                    <TimeOfDelivery>Morning</TimeOfDelivery>
                    <DeliveryLocation>back</DeliveryLocation>
                  </UpTown>
                </NewYork>
              </State>
              <State>
                <NewYork>
                  <UpTown>
                    <TimeOfDelivery>Evening</TimeOfDelivery>
                    <DeliveryLocation>side</DeliveryLocation>
                  </UpTown>
                </NewYork>
              </State>
              <State>
                <NewYork>
                  <UpTown>
                    <TimeOfDelivery>Afternoon</TimeOfDelivery>
                    <DeliveryLocation>front</DeliveryLocation>
                  </UpTown>
                </NewYork>
              </State>
            </States>
            </Item4>
        </DeliveryLocations>
        
        <DeliveryLocations>
        <Location>South East </Location>
          <Item1>Totally Full </Item1>
          <Item2>Half Empty</Item2>
          <Item3 attr1="5" attr2="6" />
          <Item4 istransferable="true">
            <States>
              <State>
                <Florida>
                  <UpTown>
                    <TimeOfDelivery>Early Morning</TimeOfDelivery>
                    <DeliveryLocation>front</DeliveryLocation>
                  </UpTown>
                </Florida>
              </State>
              <State>
                <Florida>
                  <UpTown>
                    <TimeOfDelivery>MidDay</TimeOfDelivery>
                    <DeliveryLocation>back</DeliveryLocation>
                  </UpTown>
                </Florida>
              </State>
              <State>
                <Florida>
                  <UpTown>
                    <TimeOfDelivery>Midnight</TimeOfDelivery>
                    <DeliveryLocation>back</DeliveryLocation>
                  </UpTown>
                </Florida>
              </State>
            </States>
            </Item4>
        </DeliveryLocations>
      </EastCoast>
  </NorthAmerica>
</AllStorage>

执行这些行,有助于查看是否可以使用元素或节点。

        Element deliveryLocationElement = (Element) allDeliveryLocations.item(j);
        Node deliveryLocationNode = (Node) allDeliveryLocations.item(j);

这是上面生成的输出。

问题 1:

是什么决定了使用元素还是节点?它会是人们期望执行的方法或要检索的数据吗?

接下来,执行以下代码行。

        System.out.println("GetFirstChild()");
        Node deliveryLocationChild = deliveryLocationNode.getFirstChild();
        System.out.println("     Node Name  : " + deliveryLocationChild.getNodeName());
        System.out.println("     Node Value : " + deliveryLocationChild.getNodeValue() );
        System.out.println("");

这是生成的输出。

由于 Location 是 DeliveryLocations 的子代,因此我应该会看到

 Node Name : Location
 Node Value : North East

问题 2:

为什么 getFirstChild() 没有按预期返回 Location?是否需要额外调用?

接下来,执行以下代码行。

        System.out.println("GetNextSibling()");
        deliveryLocationChild = deliveryLocationChild.getNextSibling();
        System.out.println("     Node Name  : " + deliveryLocationChild.getNodeName());
        System.out.println("     Node Value : " + deliveryLocationChild.getNodeValue());
        System.out.println("");

这是生成的输出。

好的,这次我打印出 Location,但它是在 getNextSibling() 之后,并且值仍然为 null。

问题 3:

为什么需要同时调用 getFirstChild() 和 getNextSibling() 才能看到第一个智利?

为什么 getNextSibling() 没有打印出 Item1 而不是 null?

我认为获得这些问题的答案将有助于更好地了解正在发生的事情以及为什么需要某些调用。

【问题讨论】:

    标签: java xml parsing


    【解决方案1】:

    看来您应该考虑的第一个问题是:

    什么是文档对象模型 (DOM),它与我在下面的发现有何关系?

    这个答案可以在DOM的正式规范中找到

    解释该参考文献,发现:

    [DOM] 中的节点不代表数据结构,它们 表示具有功能和身份的对象

    我们还找到了element 的词汇表条目:

    每个文档包含一个或多个元素,它们的边界 它们由开始标签和结束标签分隔,或者,对于空 由空元素标签组成的元素。每个元素都有一个类型,标识 按名称,并且可能具有一组属性。每个属性都有一个名称 和一个值。请参阅 XML 中的 Logical Structures [XML 1.0]

    文档对象模型一词表明 DOM 是面向对象的。因此,事实证明,DocumentNode,其中 Elements 也是节点。

    在此背景下,我们可以看到实际的 DOM 操作发生在Node 接口提供的 API 上,而 XML 标签的实际结构可以使用Element 接口发现。

    现在您的问题很容易回答:

    问题 1:是什么决定了使用元素还是节点?

    1. 如果你想操作 DOM,使用Node
    2. 如果您想从标签中获取属性,请使用Element
    3. 由于ElementNode,您可以将Element 用于所有内容

    问题 2:为什么 getFirstChild() 没有按预期返回 Location?

    Node 的第一个孩子是TextNode - 每个Node 都可能在其Element 的开始/结束标签之间包含文本。因此,每个Node 都有一个子节点,即Text Node ref1, ref2

    问题 3:为什么需要同时调用 getFirstChild() 和 getNextSibling() 才能看到第一个孩子?

    它不是。您所做的只是遍历 DOM 以到达 Node预计会成为第一个 Node - 但正如您现在所知,它不是。

    【讨论】:

      【解决方案2】:

      问题 1:是什么决定了使用元素还是节点?

      每个元素都是一个节点,但不是每个节点都是一个元素。其他类型的节点包括文本节点、评论节点等。

      问题 2:为什么 getFirstChild() 没有按预期返回 Location?

      因为树也包含文本节点。

      问题 3:为什么要同时调用 getFirstChild() 和 getNextSibling() 才能看到第一个孩子?

      不是。第一个孩子是一个文本节点,getNextSibling() 将您带到第二个孩子,这是一个元素节点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多