2014-10-08 81 views
0

我想將節點導入到「新」DOM文檔中,然後執行xPath查詢新導入的節點。我正在使用的XML沒有名稱空間。我按照標準程序來創建文檔,如圖所示:Java xPath/DOM - 將節點導入到文檔時,xPath查詢無法找到新節點(和子節點)

Document newDoc = null; 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    try { 
      DocumentBuilder builder = factory.newDocumentBuilder(); 
      newDoc = builder.newDocument(); 
    } catch (ParserConfigurationException pce) { 
     // Parser with specified options can't be built 
     pce.printStackTrace(); 
    } 

並導入節點...

// nodeToImport is a node from a prior xPath search (part of a node set) 
    Node docToRunXPathOn = newDoc.importNode(nodeToImport, true); 

後來,當我試圖運行XPath查詢如

XPathFactory xPathFactory = XPathFactory.newInstance(); 
    XPath xpath = xPathFactory.newXPath(); 

    if (docToRunXPathOn != null) { 
     try { 
      XPathExpression expr = xpath.compile("//version_id/text()"); 
      return (String)expr.evaluate(doc, XPathConstants.STRING); 
     } catch (XPathExpressionException e) { 
      logger.error(e); 
     } 
    } 

評估返回一個空字符串。樣本XML低於:

<?xml version="1.0" encoding="UTF-8"?> 
    <Version> 
     <version_id>51312</version_id> 
     <description>Some Description</description> 
    </Version> 

,我已經採用的解決方案是將DOM序列化到一個字符串,然後立即分析該字符串重新構建結構作爲新的DOM。這看起來非常低效並且倒退 - 我在導入和xPath中丟失了什麼?我原以爲這可能是因爲節點的父節點等沒有正確設置,但是當我使用克隆/採用方法(或者在導入後採用)時,可以看到相同的行爲。

任何答案/解釋/建議/想法讚賞。

+0

文檔的importNode()只導入節點的文件 - 它不添加它作爲一個子節點到現有節點。你必須分開做。例如: newDoc.getFirstChild()。appendChild(newDoc.importNode(nodeToRunXpathOn,true)); – 2014-10-08 20:59:07

+0

我在我的文章中錯過了...取代採用追加。我會明天嘗試你的建議,因爲雖然我已經向文檔添加了一個節點,但我沒有使用方法getFirstChild() – NF11624 2014-10-08 21:50:10

+0

實現了你的建議aryn.galadar,沒有運氣。仍然從xPath拉空的結果。是否有一些xPath/DOM的內部工作依賴於一些在導入節點時未更新的元數據?如果它有什麼不同,我正在使用基本的Java實現 - 沒有任何導入的解析器或任何東西。 – NF11624 2014-10-09 14:09:38

回答

0

我寫了一個小型測試用於重現,導入XPath後發現「51312」,也許有幫助。

public class ImportNodeTest { 
@Test 
public void testImportNode() throws Exception { 
    final Document newDocument = createDocument(); 
    final Element importedElement = getExistedNode(); 

    Node docToRunXPathOn = newDocument.importNode(importedElement, true); 
    newDocument.appendChild(docToRunXPathOn); 

    XPathFactory xPathFactory = XPathFactory.newInstance(); 
    XPath xpath = xPathFactory.newXPath(); 

    XPathExpression expr = xpath.compile("//version_id/text()"); 
    System.out.println(expr.evaluate(newDocument, XPathConstants.STRING)); 
} 

private Document createDocument() { 
    Document newDoc = null; 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    try { 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     newDoc = builder.newDocument(); 
    } catch (ParserConfigurationException pce) { 
     // Parser with specified options can't be built 
     pce.printStackTrace(); 
    } 
    return newDoc; 
} 


private Element getExistedNode() { 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    try { 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document document = builder.parse(new File("xml.xml")); 
     return document.getDocumentElement(); 
    } catch (Exception pce) { 
     throw new RuntimeException(pce); 
    } 

} 

}