2012-05-31 75 views
0

我有以下XML結構:XPATH在Java中:缺少父節點

<map name="testmap"> 
    <definitions> 
     <tile name="ground"> <!-- a normal tile that has no special obstacles --> 
      <centralObstacle>ground</centralObstacle> 
      <neighbourObstacles> 
       <north></north> 
       <east></east> 
       <south></south> 
       <west></west> 
      </neighbourObstacles> 
     </tile> 
     <tile name="wallE"> <!-- a ground tile with a wall obstacle at the east--> 
      <centralObstacle>ground</centralObstacle> 
      <neighbourObstacles> 
       <north></north> 
       <east>wall</east> 
       <south></south> 
       <west></west> 
      </neighbourObstacles> 
     </tile> 
    </definitions> 
</map> 

而且我想使用XPath查詢它。我想要做的是獲取所有的tile節點,然後遍歷它們以獲取所有名稱和其他相關信息(使用不同的XPATH查詢)。

由於XPATH表達式將在文檔上運行,因此我使用了nodeListToDoc()函數,該函數在this答案中提供,以將XPATH查詢(NodeList)的結果轉換爲文檔。這樣我可以首先獲得所有的Tiles,然後迭代它們以獲取Tile特定的信息。

private Document nodeListToDoc(NodeList nodes) throws ParserConfigurationException 
{ 
    Document newXmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
    Element root = newXmlDocument.createElement("root"); 
    newXmlDocument.appendChild(root); 
    for (int i = 0; i < nodes.getLength(); i++) { 
     Node node = nodes.item(i); 
     Node copyNode = newXmlDocument.importNode(node, true); 
     root.appendChild(copyNode); 
    } 
    return newXmlDocument;  
} 

我首先做的是文件解析到一個文件,然後運行查詢來獲取包含我所有瓷磚的NodeList。當我運行查詢//definitions/tile時,我得到一個包含兩個節點項的NodeList(我已經驗證了這一點),這是正確的。應用nodeListToDoc()的結果如下所示。

<?xml version="1.0" encoding="UTF-16"?> 
<root><tile name="ground"> <!-- a normal tile that has no special obstacles --> 
      <centralObstacle>ground</centralObstacle> 
      <neighbourObstacles> 
       <north/> 
       <east/> 
       <south/> 
       <west/> 
      </neighbourObstacles> 
     </tile><tile name="wallE"> <!-- a ground tile with a wall obstacle at the east--> 
      <centralObstacle>ground</centralObstacle> 
      <neighbourObstacles> 
       <north/> 
       <east>wall</east> 
       <south/> 
       <west/> 
      </neighbourObstacles> 
     </tile></root> 

到目前爲止好。現在事情變壞了。我想迭代兩個節點,創建它們的NodeList,將該NodeList轉換爲Document,然後對它們運行一些查詢。其中一個查詢是獲取每個瓦片的名稱。我想下面的代碼塊會做的伎倆:

for (int i = 0; i < nodes.getLength(); i++) { // iterate over the two nodes 
      NodeList tile = (NodeList) nodes.item(i); // create a nodelist containing only the first node 
      Document attrdoc = nodeListToDoc(tile); // convert it to a document 
} 

然而,當我打印結果樹attrdoc代表,我得到的,對於第一次迭代,結果如下:

<?xml version="1.0" encoding="UTF-16"?> 
<root> <!-- a normal tile that has no special obstacles --> 
      <centralObstacle>ground</centralObstacle> 
      <neighbourObstacles> 
       <north/> 
       <east/> 
       <south/> 
       <west/> 
      </neighbourObstacles> 
     </root> 

這是不正確的。根元素的孩子應該是平鋪的?這個元素去了哪裏?

+1

'因爲XPATH表達式將運行在一個Document'上,你爲什麼這麼認爲?你使用哪個API? 'XPath.evaluate(String,Object)'可以接受'NodeList'作爲第二個參數(這是XPath查找的上下文) –

回答

0

+1 @ @ Andy的評論。當我讀到你的問題時,我覺得你真的不想寫一份新的文件;相反,您只是將它用作從現有XML中提取信息的手段。

所以你的方法是直接從節點訪問信息。例如,在你的去路,你遍歷兩個節點,你可以做這樣的事情:

for (int i = 0; i < nodes.getLength(); i++) { // iterate over the two nodes 
    NodeList node = nodes.item(i); 
    if (node.getNodeType() == ELEMENT_NODE) { 
     Element element = (Element) node; 
     //from here, you can access element.getNodeValue(), element.getChildNodes(), etc. 
    }  
} 

此外,你可以回去newXmlDocument和應用多個XPath查詢到它。這不是一勞永逸的,因爲如果你使用的是SAX解析器。

1

你並沒有真正解釋你想達到什麼,但是你的描述真的讓我懷疑Java + XPath是否是適合這項工作的正確工具。你看過在XQuery或XSLT中做這件事嗎?