是否需要在根元素中声明XML命名空间以便通过XPath查询进行匹配?
我无法弄清楚XPath本身是否应该受到指责,或者是否是特定的XPath实现使得这一点变得如此困难. SO问题 –
How to change an an XML element in a namespace with MSDeploy Parameters.xml file? – 是我的灵感来源.
什么行不通 这是不起作用的基本示例. XML: <spring> <objects xmlns="http://www.springframework.net"> <object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver,Spring.Web"> <!--configure for server--> <property name="DefaultCulture" value="en" /> </object> </objects> </spring> XPath的: //spring/objects/object[@id='CultureResolver']/@type XPath查询不返回任何内容,而不是: Spring.Globalization.Resolvers.SessionCultureResolver,Spring.Web 我期待的工作 我或许天真地希望以下方面有效. 修改后的XML: <spring> <spring:objects xmlns:spring="http://www.springframework.net"> <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver,Spring.Web"> <!--configure for server--> <spring:property name="DefaultCulture" value="en" /> </spring:object> </spring:objects> </spring> 修改过的XPath查询: //spring/spring:objects/spring:object[@id='CultureResolver']/@type 此查询在我使用的the online tester中引发错误: ERROR - Failed to evaluate XPath expression: org.apache.xpath.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: spring 什么工作 修改后的XML: <spring xmlns="" xmlns:spring="http://www.springframework.net"> <spring:objects> <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver,Spring.Web"> <!--configure for server--> <spring:property name="DefaultCulture" value="en" /> </spring:object> </spring:objects> </spring> 修改过的XPath查询(与我期望的工作相同): //spring/spring:objects/spring:object[@id='CultureResolver']/@type 为了增加混淆,我发现以下XPath查询适用于原始示例XML(在在线测试器XPath引擎中): //spring/*[local-name() = 'objects' and namespace-uri() = 'http://www.springframework.net']/*[@id='CultureResolver' and local-name() = 'object' and namespace-uri() = 'http://www.springframework.net']/@type 为什么? 由于命名空间和前缀之间的相互作用,这是否令人困惑?似乎声明没有前缀的命名空间不仅包括该命名空间中的相关元素,还包括其所有子节点,因此将其描述为“默认命名空间”(如this answer中的相关问题).声明带有前缀的命名空间甚至不包括该命名空间中的相关元素! 是否有某些原因需要将名称空间包含在XML文档的根元素中,而不依赖于特定的XPath实现? 我的XPath引擎 我试图解决的问题涉及Microsoft Web Deploy(MSDeploy)使用的任何XPath引擎. 我也在使用this online XPath tester.
一个有趣且问题很好的问题!据我所知,难点在于XPath引擎处理输入文档中的命名空间声明的方式.
简短的回答 不,这种行为一般与XPath或XPath规范无关.这是由于个别实施. 规格说什么 就XML和XPath规范而言,名称空间可以在任何元素上声明,并且最外层(或“根”)元素没有什么特别之处.根元素上的命名空间声明就像任何其他声明一样. 当然还有规则.例如,前缀必须与使用其QName的元素上的名称空间URI相关联,或者与该元素(或该属性的)的祖先相关联.所以,以下不是格式良好的XML: <prefix:root> <child xmlns:prefix="www.example.com"/> </prefix:root> 第二个重要规则:默认命名空间只能应用于声明它的元素和所有后代元素.在以下文档中,根元素根本没有命名空间: <root> <child xmlns="www.example.com"> <grandchild/> </child> </root> 我所说的规格是XML,XML Namespaces和Xpath规格. 在XPath的实现中会发生什么 现在,如果针对XML文档计算XPath表达式,则此输入文档中存在的所有名称空间声明也必须明确地可用于(声明或“注册”)到XPath引擎. XPath的一些实现通过简单地重新声明在作为Xpath引擎的输入的XML文档的元素或属性的范围内的所有名称空间声明来简化这一点(也见this). 在您的情况下,似乎只考虑在最外层元素上做出的声明.这就是你最后一个XML文档的原因: <spring xmlns="" xmlns:spring="http://www.springframework.net"> <spring:objects> <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver,Spring.Web"> <!--configure for server--> <spring:property name="DefaultCulture" value="en" /> </spring:object> </spring:objects> </spring> works – 因为名称空间声明是在根元素上进行的,并且您从根元素执行XPath表达式.您可以省略默认命名空间的未声明,因为它没有任何效果. 最后,回答你的上一个问题:
不,没有理由命名空间声明应该在根元素上,除了 >在我看来,在根元素上声明它们更容易找到(非常主观) 如果您的XPath实现自动重新声明范围内的命名空间声明,您当然可以利用它,但有时也会让您感到困惑,正如您所注意到的那样. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |