2013-12-10 65 views
0

我习惯于C++库进行xml解析,即rapidxml和tinyxml。内置在DOM解析器中的java对我来说绝对没有意义。经过一番斗争后,我能够存储我需要的根节点,但现在我想要找到具有特定ID的标签。如何找到具有特定属性值的子元素

下面是一个示例的xml:

<?xml version="1.0" encoding="UTF-8"?> 
<adventure title="Test Adventure" author="Tester"> 
    <enemies> 
     <enemy id="e1" difficulty="1">Enemy1</enemy> 
    </enemies> 
    <story> 
     <narration id="n1" action="d1">It's adventure time!</narration> 
     <decision id="d1"> 
      <description>Would you like to participate?</description> 
      <choice action="n2">Yes, please.</choice> 
      <choice action="n3">Not the slightest.</choice> 
     </decision> 
     <narration id="n2" action="end">Great choice!</narration> 
     <narration id="n3" action="end">Okay...</narration> 
    </story> 
</adventure> 

我有存储在Node实例<story>节点。从那里,我想找到具有特定ID的节点(假设'n3'节点)。

我想用这个方法:

private Node findNode(String id) { 
    Node node = storyNode.getFirstChild(); 
    while (node != null) { 
     Element elem = (Element)node; 
     if (elem.getAttribute("id") == id) { 
      return node; 
     } 
     node = node.getNextSibling(); 
    } 

    return null; 
} 

这将是我的方式去与C++库,但这是工作很远......我不明白为什么我要强制转换为了这么简单的任务。为什么Node不能通过指定属性名称来获取属性。 getFirstChild()甚至似乎不会返回第一个孩子...

我在网上找到的包装类是30深循环,甚至更难使用。为什么这很复杂?我究竟做错了什么?

+0

奇怪的是,这是非常相似的在.Net库中的工具,所以我假设它是基于来自标准机构的推荐,谁可能设计了解决方案,并且从来不必使用... – MadProgrammer

+0

@Ma dProgrammer真的很疯狂。 NodeList必须迭代,但不能与迭代器一起使用,因为获取节点的唯一方法是使用'.item(index)'方法,该方法返回一个'Node',它可以*一个'元素',它继续,并继续... 我需要三个方法,一个可以抓住下一个兄弟,一个返回一个特定的子元素,或第一个,如果它被称为没有参数,第三个读取特定的属性。如果我想,我不能让这更难,但这里真的是错误的。 – Innkeeper

+0

就我个人而言,我写了一个小库来“包装”疯狂...是的,我甚至写了一个'IterableNodeList' ...我的直觉是它是由工程师设计和编写的......非常好的论文..对于实际上不得不使用它的人来说不是那么多;) – MadProgrammer

回答

2

为什么这个API是如此...真棒...会回到为什么和它是如何设计的。那么你的想法可能会比较简单。

您可以使用的功能之一是XPath实现,它被吹捧为XML的查询语言。

因此,而不是通过每个节点,每个子节点试图循环,你可以简单地使用类似//*[@id='n1']找到与id属性,它等于n1(例如)的任何节点。

使用您的示例XML和下面的代码...

try { 
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("Test.xml")); 
    Node root = doc.getDocumentElement(); 

    XPath xPath = XPathFactory.newInstance().newXPath(); 

    XPathExpression xExpress = xPath.compile("//*[@id='n1']"); 
    NodeList nl = (NodeList)xExpress.evaluate(root, XPathConstants.NODESET); 

    System.out.println("Found " + nl.getLength() + " matches"); 
} catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException ex) { 
    ex.printStackTrace(); 
} 

此输出

Found 1 matches 

看看XPath的一些细节

相关问题