2013-12-10 202 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的一些細節

相關問題