首页 文章

Html,xmlns,命名空间,xml

提问于
浏览
1

我刚用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);

根据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);

然后,我使用// 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 ...

谢谢

2 回答

  • 9

    你误解了你所读到的内容 . xmlns 属性的名称空间本身必须是 http://www.w3.org/2000/xmlns/ . 默认命名空间(通过 xmlns="something" 指定的命名空间可以,或者当然可以更改) .

    注意

    <element1 xmlns="something">
        <element2/>
    </element1>
    

    是相同的

    <x:element1 xmlns:x="something">
        <x:element2/>
    </x:element1>
    

    换句话说,默认命名空间只是一个方便的缩写,它允许您不为默认命名空间中的元素指定前缀 .

  • 1

    你的问题中存在很多混乱,如果不编写关于XML命名空间的完整教程,解决它并不容易 . 我将尽可能地覆盖它们与(X)HTML的关系 .

    首先,命名空间的目的是分离词汇表 . 因此,例如, http://www.w3.org/1999/xhtml 命名空间中的 title 元素可以与 http://www.w3.org/2000/svg 命名空间中的 title 元素区分开来,当它们出现在同一文档中或由公共处理器处理时 .

    其次,忘记 http://www.w3.org/2000/xmlns/ 命名空间 . 它的作用主要在幕后,你很少需要担心它 .

    接下来,我们需要区分null名称空间,默认名称空间和前缀引用的名称空间 .

    当XML文件没有定义 xmlns= 属性时,所有未加前缀的元素都被认为是'in the null namespace'或'in no namespace',这相当于同一件事 .

    当XML元素具有 xmlns= 属性时,它及其后代元素(如果它们没有前缀)被称为'in the default namespace',其中默认命名空间是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解析器就好了忽略命名空间以映射前缀,并简单地"knows"哪些元素名称属于哪些命名空间 . 这使得它最终不那么灵活,但在其专业领域内,更强大且易于使用 . (在上面的 title 元素的示例中,它通过查看 title 的祖先元素来确定应用哪个命名空间)这就是为什么XHTML文档不能识别它们的原因 .

    浏览器(无论如何都是现代的),然后有专门的DOM类API方法和CSS规则来隐藏所有这些命名空间复杂性远离javascript和css作者,因此,在大多数情况下,网页作者可以安全地忽略命名空间 .

    但是,独立的HTML解析器并不总是这样做 . 相反,它们将所有元素放在null命名空间中,这意味着可以使用标准DOM API找到不包含元素名称前缀的xpath . 对于大多数实际用途,这与浏览器使用HTML解析器进行解析时的情况相同 .

    因此,总而言之,您需要了解您是使用XML还是HTML解析器解析XHTML,以及该特定解析器如何将元素分配给命名空间,以便能够编写正确的xpath来查询其中的元素该文件 .

相关问题