解析具有相同名称的嵌套XML标记

时间:2010-03-21 15:59:48

标签: xml dom java

我们来看一个简单的XML文档:

  <x>
    <e>
        <e>
            <e>Whatever 1</e>
        </e>
    </e>
    <e>
        <e>
            <e>Whatever 2</e>
        </e>
    </e>
    <e>
        <e>
            <e>Whatever 3</e>
        </e>
    </e>
  </x> 

使用标准的org.w3c.dom,我可以通过执行..来获取X中的节点。

NodeList fullnodelist = doc.getElementsByTagName("x");

但如果我想返回下一组“e”,我会尝试使用类似的东西。

Element element = (Element) fullnodelist.item(0);
NodeList nodes = pelement.getElementsByTagName("e");

期望它返回“3”节点(因为有3组“e”),但相反,它返回“9” - 因为它会以“e”显示所有条目。

在上述情况下这很好,因为我可能会迭代并找到我正在寻找的东西。我遇到的问题是,当XML文件如下所示:

  <x>
    <e>
      <pattern>whatever</pattern>
      <blanks>
        <e>Something Else</e>
      </blanks>
    </e>
    <e>
      <pattern>whatever</pattern>
      <blanks>
        <e>Something Else</e>
      </blanks>
    </e>
  </x>

当我请求“e”值时,它返回4,而不是(我期望的)2。

我只是不了解DOM解析的工作原理?通常在过去我使用自己的XML文档,所以我永远不会命名这样的项目,但不幸的是,这不是我的XML文件,我没有选择像这样工作。

我认为我会做的是编写一个“向下钻取”节点的循环,以便我可以将每个节点组合在一起......

public static NodeList getNodeList(Element pelement, String find)
    {
        String[] nodesfind = Utilities.Split(find, "/");
        NodeList nodeList = null;

        for (int i = 0 ; i <= nodesfind.length - 1; i++ )
        {
            nodeList = pelement.getElementsByTagName( nodesfind[i] );
            pelement = (Element)nodeList.item(i);
        }

        // value of the nod we are looking for
        return nodeList;
    }

..所以如果你把“s / e”传递给函数,它会返回我正在寻找的2个节点(或元素,也许我使用的术语不正确?)。相反,它返回该节点内的所有“e”节点。

我正在使用J2SE,所以选项相当有限。我不能使用任何第三方XML Parsers。

无论如何,如果有人还在我身边并有建议,我们将不胜感激。

3 个答案:

答案 0 :(得分:3)

如果您是手动遍历Xml,请尝试使用一个变量,当您遇到每个“e”标记时,该变量会递增,然后在您离开时递减。

如果源代码遵循您给出的上述示例,则可以使用简单的if语句在执行操作之前确保计数器等于2(假设它从0开始)

我可能会稍微误解你的确切问题,但我希望这会有所帮助。

答案 1 :(得分:2)

比计数器更好的解决方案是检查每个返回的节点,看看它们是否具有正确的父节点。

getChildNodes()不仅返回所有子项,还返回所有后代(即完整子树)。

  Element element = doc.getDocumentElement();
  NodeList nodeList = element.getChildNodes();
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      if (childElement.getTagName().equals("someTagName")) {
        handleSomeTag(childElement);
      } else if (childElement.getTagName().equals("someOtherTagName")) {
        handleSomeOtherTag(childElement);
      }
    }
  }

getElementsByTagName()不仅返回具有该标记名的所有子项,还返回具有该标记名的所有后代(即完整子树中具有该名称的所有标记)。

  Element element = doc.getDocumentElement();
  NodeList nodeList = element.getElementsByTagName("someTag");
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      handleSomeTag(childElement);
    }
  }
  nodeList = element.getElementsByTagName("someOtherTag");
  for (int i = 0; i < nodeList.getLength(); i++ ) {
    if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE && nodeList.item(i).getParentNode().isSameNode(element)) {
      Element childElement = (Element) nodeList.item(i);
      handleSomeOtherTag(childElement);
    }
  }

答案 2 :(得分:1)

您需要了解XPath。 Java 1.5中有一个XPathFactory,您可以创建一个XPath来命名您想要的特定“e”。