2012-03-12 45 views
2

我想解析由XOM的外部系統返回的一些HTML。該HTML如下:(其實它顯著理出頭緒,但它有這個DOCTYPE聲明,這些名字空間和語言的聲明,以上展品HTML同樣的問題,因爲真正的HTML)使用XPath從具有不必要的命名空間的文檔中提取XOM元素

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<body> 
    <div> 
    Help I am trapped in a fortune cookie factory 
    </div> 
</body> 
</html> 

我想要做的是提取<div>的內容,但命名空間聲明似乎令XPath變得令人困惑。如果我帶出空間聲明(用手,從文件),下面的代碼查找<div>,沒問題:

Document document = ... 
Nodes divs = document.query("//div"); 

但與命名空間,返回Nodes的大小爲0。

好的,如果我以編程方式剝離命名空間,怎麼樣?

Element rootElement = document.getRootElement(); 
rootElement.removeNamespaceDeclaration(rootElement.getNamespacePrefix()); 

...看起來應該可以工作,但什麼都不做。從javadoc

此方法僅刪除與addNamespaceDeclaration.

好增加額外的命名空間,我想,我會提供命名空間查詢:

XPathContext context = 
    XPathContext.makeNamespaceContext(document.getRootElement()); 
Nodes divs = document.query("//div", context); 

大小仍爲零。

如何手動構建名稱空間上下文?

XPathContext context = context = new XPathContext(
    rootElement.getNamespacePrefix(), rootElement.getNamespaceURI()); 
Nodes divs = document.query("//div", context); 

XPathContext構造吹了:

nu.xom.NamespaceConflictException: 
    XPath expressions do not use the default namespace 

所以,我在尋找之一:

  1. 一個方法,使這項工作查詢,或
  2. 方式以編程方式剝離名稱空間聲明或
  3. 解釋正確的a pproach,假設這兩個都是錯誤的。

更新:基於Lev Levitsky's answerJaxen FAQ我想出了下面的技巧:

XPathContext context = new XPathContext(
    "foo", 
    document.getRootElement().getNamespaceURI()); 
Nodes divs = document.query("//foo:div"); 

這仍似乎有點瘋狂的給我,但我想它的方式Jaxen的要你做事。


更新#2:正如下面和all over the Internet指出,這不是Jaxen的的錯;它只是XPath的XPath。

所以,雖然這個黑客的作品,我仍然喜歡一種方式來剝離命名空間聲明。最好不要XSLT。

+0

這是XPath的工作原理與命名空間的方式,它不依賴於Jaxen的:如果你想匹配與命名空間的東西,你必須在XPath – MiMo 2012-03-13 01:21:33

+0

使用一個明確的前綴是的,在進一步的閱讀中我看到了。所以,好吧,Jaxen沒有責備,但它似乎仍然有點瘋狂。或者,充其量是迂腐的,主要是爲了在不切實際的用例中達到最大的正確性。 – 2012-03-14 23:17:54

回答

1

您應接受什麼直接指定命名空間像

Nodes divs = document.query("//{http://www.w3.org/1999/xhtml}div"); 

或使用映射到相應的命名空間前綴(我猜這就是NamespaceContext是,但是沒有前綴在查詢)。

不幸的是,我不知道它是如何在Java中實現的,但是如果有幫助的話,我可以提供一個Python示例。

2

你可以寫:

Nodes divs = document.query("//*[local-name()='div' and namespace-uri()='http://www.w3.org/1999/xhtml']"); 
相關問題