Seb*_*ber 2 html xml namespaces xml-namespaces
我在使用nekohtml + dom4j解析html文档时遇到了一些问题.
我发现我的xpath表达式不再起作用了,因为最近在html源上添加了一个新的默认html xml命名空间.
规格说:
前缀xmlns仅用于声明名称空间绑定,并且根据定义绑定到名称空间名称 http://www.w3.org/2000/xmlns/.它不能被宣布.其他前缀不得绑定到此命名空间名称,并且不得将其声明为默认命名空间.元素名称不能有前缀xmlns.
但在我的html文档中,最近(我猜)在html标签中添加了:xmlns ="http://www.w3.org/1999/xhtml"
我找到了2个解决方案
1)删除命名空间:
DOMParser parser = new DOMParser();
parser.setFeature("http://xml.org/sax/features/namespaces", false);
parser.parse(url);
Run Code Online (Sandbox Code Playgroud)
根据NekoHTML faq的说法.
2)为我的xpath添加一个前缀,绑定到默认的html命名空间.(似乎它不能将前缀"空字符串"绑定到我想要的命名空间)
Map<String,String> XPATH_NAMESPACES = new HashMap<String, String>();
XPATH_NAMESPACES.put("my_prefix", "http://www.w3.org/1999/xhtml");
XPath xpath = document.createXPath(xpathExpr);
xpath.setNamespaceURIs(XPATH_NAMESPACES);
Element element = (Element) xpath.selectSingleNode(document);
Run Code Online (Sandbox Code Playgroud)
然后,我使用// my_prefix:td而不是使用// td作为例子
我发布这些解决方案,因为有些人可能会发现这篇文章很有用.另见http://www.edankert.com/defaultnamespaces.html#Jaxen_and_Dom4J
但我真正想知道的是:
我想我的问题对你们中的一些人来说似乎很明显,但我并没有真正意识到它带来了什么.我已经读过html和xhtml之间的区别.我想使用xhtml dtd的人宁愿使用这个命名空间,但除了它给爬虫或其他类似的东西带来一些额外的痛苦之外,还有什么真正的兴趣?
PS:我已经看到从html传递到xhtml你必须添加xmlns和xml:lang,例如:所以它可能不是我解析的网站的目的,因为没有添加xml:lang ...
谢谢
Alo*_*hci 10
你的问题中存在很多混淆,如果不编写关于XML命名空间的完整教程,解决它并不容易.我将尽可能地覆盖它们与(X)HTML的关系.
首先,命名空间的目的是分离词汇表.因此,例如,所述title在元件http://www.w3.org/1999/xhtml命名空间可从区分title在元件http://www.w3.org/2000/svg的命名空间,当它们出现在同一文档中,或者通过一个公共处理器处理.
其次,忘记http://www.w3.org/2000/xmlns/命名空间.它的作用主要在幕后,你很少需要担心它.
接下来,我们需要区分null名称空间,默认名称空间和前缀引用的名称空间.
当XML文件没有xmlns=定义属性时,所有未加前缀的元素都被称为"在null名称空间中",或者"在没有名称空间中",这相当于同一个东西.
当XML元素具有xmlns=属性时,它及其后代元素(如果它们没有前缀)被称为"在默认命名空间中",其中默认命名空间是xmlns属性的值.
前缀元素始终位于由xmlns:prefix=元素的元素或祖先中的属性映射的命名空间中.
现在,XHTML词汇表被定义为http://www.w3.org/1999/xhtml命名空间中的元素,因此正确编写的XHTML文档将声明该命名空间作为默认命名空间,或者将前缀映射到命名空间,在这种情况下,所有XHTML元素都需要包含他们名字上的那个前缀.(由于下面给出的原因,后一种情况不会经常发生).
因此,在使用XML解析器解析XHTML时,名称空间映射需要存在.
但是,XPath没有默认命名空间的概念.如果未将前缀放在xpath中指定的元素上,它将尝试匹配null命名空间中的元素.如果XHTML元素在http://www.w3.org/1999/xhtml命名空间中,则xpath将不匹配任何内容.
这是它开始变得复杂的地方 - 浏览器.
如果您按照自己的意愿向浏览器提供XHTML网页,使用XML内容类型(如application/xhtml + xml),浏览器将使用XML解析器加载它,并应用上述所有规则.如果您不包含该xmlns="http://www.w3.org/1999/xhtml"属性,浏览器将无法理解如何处理该属性,只会将该文件显示为原始XML结构.
但是,因为IE直到IE9不支持XML内容类型,所以几乎没有人以这种方式提供网页.相反,他们使用"text/html"内容类型,在这种情况下,浏览器根本不使用XML解析器,它使用HTML.
HTML解析器只是忽略命名空间以映射前缀,并简单地"知道"哪些元素名称属于哪些命名空间.这使得它最终不那么灵活,但在其专业领域内,更强大且易于使用.(在title上面元素的示例中,它通过查看titles祖先元素来确定应用哪个命名空间)这就是为什么XHTML文档不使用前缀元素,因为HTML解析器无法识别它们.
浏览器(无论如何都是现代的),然后有专门的DOM类API方法和CSS规则来隐藏所有这些命名空间复杂性远离javascript和css作者,因此,在大多数情况下,网页作者可以安全地忽略命名空间.
但是,独立的HTML解析器并不总是这样做.相反,它们将所有元素放在null命名空间中,这意味着可以使用标准DOM API找到在元素名称上不包含前缀的xpath.对于大多数实际用途,这与浏览器使用HTML解析器解析时的情况相同.
总而言之,您需要了解您是使用XML或HTML解析器解析XHTML,以及该特定解析器如何将元素分配给命名空间,以便能够编写正确的xpath来查询其中的元素该文件.
| 归档时间: |
|
| 查看次数: |
4999 次 |
| 最近记录: |