是否需要在根元素中声明XML名称空间,以便XPath查询可以匹配它? [英] Do XML namespaces need to be declared in the root element to be matchable by an XPath query?

查看:82
本文介绍了是否需要在根元素中声明XML名称空间,以便XPath查询可以匹配它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道应该归咎于XPath本身,还是造成这种困难的特殊的XPath实现. SO问题–

I can't figure out whether XPath itself is to blame or whether it's the particular XPath implementations that make this so difficult. The SO question – How to change an an XML element in a namespace with MSDeploy Parameters.xml file? – was my inspiration.

这是不起作用的基本示例.

Here's the basic example that doesn't work.

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查询不返回任何内容,而是:

The XPath query returns nothing instead of:

Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web

我期望的工作

我可能天真地希望以下工作有效.

What I Expect to Work

I would, perhaps naively, expect the following to work.

修改后的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查询:

Modified XPath query:

//spring/spring:objects/spring:object[@id='CultureResolver']/@type

此查询在我使用的在线测试仪中引发错误:

ERROR - Failed to evaluate XPath expression: org.apache.xpath.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: spring

什么起作用

修改后的XML:

What Does Work

Modified 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查询(与我期望的工作相同):

Modified XPath query (same as under What I Expect to Work):

//spring/spring:objects/spring:object[@id='CultureResolver']/@type

为了使您更加困惑,我发现以下XPath查询适用于原始示例XML(在在线测试器XPath引擎中):

To add to the confusion somewhat, I discovered that the following XPath query works for the original example XML (in the online tester XPath engine):

//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

为什么?

这是不是因为名称空间和前缀之间的相互作用而引起混淆?似乎声明没有前缀的名称空间不仅包含该名称空间中的相关元素,而且还包含其所有子元素,因此将其描述为默认名称空间"(例如

Why?

Is this confusing because of the interplay between namespaces and prefixes? It seems like declaring a namespace without a prefix not only includes the relevant element in that namespace but also includes all of its children too, hence describing it as a "default namespace" (like in this answer to a related question). Whereas declaring a namespace with a prefix doesn't even include the relevant element in that namespace!

是否有某些原因需要将命名空间 包含在XML文档的根元素中,而与特定的XPath实现无关?

Is there some reason why namespaces need to be included in the root element of the XML document, independent of particular XPath implementations?

我要解决的问题涉及Microsoft Web Deploy(MSDeploy)使用的XPath引擎.

The problem I was trying to solve involved whatever XPath engine that Microsoft Web Deploy (MSDeploy) uses.

我还使用了此在线XPath测试器.

推荐答案

一个有趣且要求很高的问题!据我所知,困难在于您的XPath引擎处理在输入文档中找到的名称空间声明的方式.

An interesting and well-asked question! As far as I can see, the difficulty lies with the way your XPath engine handles namespace declarations found in the input document.

简短答案

否,此行为与XPath通常或XPath规范无关.这是由于单独的实现.

No, this behaviour has nothing to do with XPath in general or with the XPath specification. It is due to individual implementations.

规范怎么说

就XML和XPath规范而言,可以在任何元素上声明名称空间,并且最外面的(或根")元素没有什么特别的.根元素上的命名空间声明与其他任何声明一样.

As far as the XML and XPath specifications are concerned, namespaces can be declared on any element, and there is nothing special about the outermost (or "root") element. Namespace declarations on the root element are just like any other declaration.

当然还有规则.例如,前缀必须与使用其QName的元素上或该元素(或该属性)的祖先上的名称空间URI关联.因此,以下不是格式正确的XML:

Of course there are still rules. For instance, a prefix must be associated with a namespace URI on the element in whose QName it is used, or on an ancestor of that element (or of that attribute). So, the following is not well-formed XML:

<prefix:root>
    <child xmlns:prefix="www.example.com"/>
</prefix:root>

第二个重要规则:默认名称空间只能应用于声明了它的元素和所有后代元素.在以下文档中,root元素根本没有命名空间:

And the second important rule: A default namespace can only apply to the element on which it is declared and all descendant elements. In the following document, the root element is in no namespace at all:

<root>
   <child xmlns="www.example.com">
      <grandchild/>
   </child>
</root>

我要讨论的规范是 XML XML命名空间

The specifications I am talking about are the XML, XML Namespaces and Xpath specifications.

实施XPath会发生什么情况

现在,如果根据XML文档对XPath表达式进行了评估,则还必须使该输入文档中存在的所有名称空间声明都可以显式地提供给XPath引擎(声明或注册").

Now, if an XPath expression is evaluated against an XML document, all namespace declarations present in this input document must also explicitly be made available (declared, or "registered") to the XPath engine.

XPath的某些实现通过简单地重新声明作为Xpath引擎输入的XML文档的元素或属性范围内的所有命名空间声明,简化了此操作(另请参见

Some implementations of XPath simplify this by simply redeclaring all namespace declarations that are in scope for an element or attribute of an XML document that serves as input for an Xpath engine (also see this).

在您的情况下,似乎仅考虑在最外层元素上进行的声明.这就是您上一个XML文档的原因:

In your case, it seems only declarations made on the outermost element are considered. That's why your last XML document:

<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表达式.不过,您可以省略对默认名称空间的取消声明,因为它没有任何作用.

works - because the namespace declaration is made on the root element and you execute the XPath expression from the root element. You could omit the undeclaration of a default namespace though, because it doesn't have any effect.

最后,回答您的最后一个问题:

Finally, to answer your last question:

是否存在某些原因需要将名称空间包含在XML文档的根元素中,而与特定的XPath实现无关呢?

Is there some reason why namespaces need to be included in the root element of the XML document, independent of particular XPath implementations?

否,没有理由在根元素上声明名称空间,除了

No, there is no reason namespace declarations should be on the root element, except

  • 在我看来(高度主观),在根元素上声明它们时,它们会更容易找到
  • 如果您想为整个文档声明一个默认的名称空间.在根元素上声明它是使其也应用于根元素的唯一方法
  • 如果根元素本身具有限定名称,即为前缀.然后,必须在根元素上声明此前缀和名称空间URI.
  • that they are somewhat easier to find when declared on the root element, in my opinion (highly subjective)
  • if you'd like to declare a default namespace for the whole document. Declaring it on the root element is the only way to have it also apply to the root element
  • if the root element itself has a qualified name, i.e. is prefixed. Then, you must declare this prefix and namespace URI on the root element.

如果XPath的实现自动重新声明作用域中的名称空间声明,那么您当然可以利用它,但是,正如您所注意到的那样,有时也会造成混淆.

If your implementation of XPath automatically redeclares namespace declarations that are in scope, you can of course take advantage of it, but it will also be confusing sometimes, as you have noticed.

这篇关于是否需要在根元素中声明XML名称空间,以便XPath查询可以匹配它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆