2012-07-23 54 views
1

我正在做一個輸入XML的XSL轉換,然後我需要在生成的文檔上使用XPath提取一些值。但是,在使用XSL結果節點時,XPath表達式總是返回null。 但是,如果我將XSL生成的文檔存儲在一個文件中,然後重新加載它。 XPath表達式返回相應的節點。XSL轉換,然後生成的節點上的XPath表達式

這裏是我的代碼(實用fonctions已爲lisibility刪除):

public class XmlTest { 
@Test 
public void testWithNativeJavaApi() throws Exception { 
    InputStream instream = resolveClasspathFile("xslt/xslt-test-transform-2.xsl"); 
    StreamSource xsltSource = new StreamSource(instream); 
    DOMSource domSource = loadXmlFromClasspathFile("xslt/xslt-test-input-2.xml"); 
    prettyPrint(domSource.getNode()); 

    Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource); 
    DOMResult domResult = new DOMResult(); 
    transformer.transform(domSource, domResult); 
    Node node = domResult.getNode(); 

    // Store then reload the file 
    // Uncommenting those 3 lines will make the test pass 
    // File xslOutputfile = new File("target", "xsl-ouput.xml"); 
    // prettyPrint(node, new FileOutputStream(xslOutputfile)); 
    // node = loadXmlFromInputStream(new FileInputStream(xslOutputfile)).getNode(); 

    XPath xPathProcessor = XPathFactory.newInstance().newXPath(); 
    XPathExpression xpathExpression = xPathProcessor.compile("/Message/Out/Personne/CodeCivilite"); 
    System.out.println(); 
    Node resultNode = (Node) xpathExpression.evaluate(node, XPathConstants.NODE); 

    if (resultNode != null) { 
     System.out.println(resultNode.getNodeName() + "=" + resultNode.getTextContent()); 
    } else { 
     System.out.println("Node is null"); 
    } 

    assertNotNull("XPath expression returned null node", resultNode); 
    assertEquals("CodeCivilite", resultNode.getNodeName()); 
    assertEquals("M.", resultNode.getTextContent()); 

} 
} 

中庸之道註釋或刪除下面的「//商店然後重新裝入文件」,測試將不再通過3線。

我完全卡住了,歡迎任何幫助。

回答

1

除非使用dbf.setNamespaceAware(true),否則默認情況下DocumentBuilderFactory不使用命名空間。另一方面,XSL和TransformerFactory充分使用名稱空間,以便轉換的結果文檔使用名稱空間進行限定。

因此,在XSL轉換旁邊調用XPathExpression時應該使用名稱空間。

XPath xPathProcessor = XPathFactory.newInstance().newXPath(); 
xPathProcessor.setNamespaceContext(new NamespaceContext() { 
    @Override 
    public String getNamespaceURI(String prefix) { 
    if(prefix.equals("t")) { 
     return "http://www.example.org/test"; 
    } else { 
     return null; 
    } 
    } 
    @Override public String getPrefix(String namespaceURI) { 
    return null; // not used 
    } 
    @Override 
    public Iterator<?> getPrefixes(String namespaceURI) { 
    return null; // not used 
    } 
}); 
XPathExpression xpathExpression = xPathProcessor.compile("/t:Message/t:Out/t:Personne/t:CodeCivilite"); 
System.out.println(); 
Node resultNode = (Node) xpathExpression.evaluate(node, XPathConstants.NODE); 

引入一個臨時文件,具有默認的DocumentBuilderFactory(不知道名字空間的)重載使非限定的XPath表達式(沒有命名空間)的工作。

希望這是明確的:)

0

我不知道解析文件是否給你一棵較短的樹。嘗試使用XPath表達式

//Message/Out/Personne/CodeCivilite 

(在前面雙斜線),而不文件I/O,以查看是否有節點沒有文件I/O的額外層。

0

node = loadXmlFromInputStream(new FileInputStream(xslOutputfile))。 getDocumentElement();

它是getDocumentElement()?

你可以打印重新加載的節點,看看你是否有你所期望的?

+0

隨着3線存儲和重新加載XML文檔,它是工作,但是當我不這樣做(通過評論那些3線),它不工作了。 – Mektoub 2012-07-24 07:36:44

+0

只需使用「/」的XpathExpression獲取節點,然後打印並查看已轉換文檔的根目錄。另外嘗試「//」。另一個懷疑是某種名稱空間阻止了搜索。 – 2012-07-25 18:01:55

+0

我找到了解決方案。這是一個命名空間問題。 – Mektoub 2012-07-26 07:21:04