当我删除前缀时,XPath 返回 null

发布于 2024-10-31 13:54:56 字数 884 浏览 6 评论 0 原文

我在 Eclipse 下的 Java 中使用 XPath。我正在编写一个 SOAP Web 服务,XML 使用前缀和命名空间,我想删除前缀并只保留命名空间,因为我更喜欢更具可读性的 XML 文档。

当我从 XML 定义文件中删除前缀并尝试使用 XPath 查询 XML 时,我开始为 XML 中的每个节点获取 null!

我的问题是,如果我想使用 XPath,是否必须使用前缀?仅仅命名空间就足够了吗?

<myrequest
    xmlns="http://www.mywebsite.com/xml/webservice"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.mywebsite.com/xml/webservice Request.xsd">

   <state>     
       <value>demox</value>

这就是我的 XML 的启动方式,当我使用像 XPath.selectSingleNode() 这样的 XPath 查询它时,我总是从 XPath 中的每个节点收到 null 。

String myExpression = "myrequest/state/value";  
Document doc = new Document(requestXML);    
Element e = doc.getRootElement();
request.setMybase(getBase((org.jdom.Element) 
            XPath.selectSingleNode(doc,myExpression)));

I am using XPath in Java under Eclipse. I am writing a soap web service, the XML is using prefix and a namespace and I wanted to remove the prefix and only keep the namespace because I prefer a more readable looking XML document.

When I removed the prefixes from XML definition file and tried to query the XML with XPath I started to get null for every node in the XML!

My question is do I have to use a prefix if I want to use XPath? isn't just namespace is enough?

<myrequest
    xmlns="http://www.mywebsite.com/xml/webservice"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.mywebsite.com/xml/webservice Request.xsd">

   <state>     
       <value>demox</value>

this is how my XML starts and when I query this with XPath like XPath.selectSingleNode() I always receive null from the XPath for every node in it.

String myExpression = "myrequest/state/value";  
Document doc = new Document(requestXML);    
Element e = doc.getRootElement();
request.setMybase(getBase((org.jdom.Element) 
            XPath.selectSingleNode(doc,myExpression)));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风情万种。 2024-11-07 13:54:56

这是关于几个 XPath 相关标签的常见问题解答

只要 XML 文档中有默认命名空间(如您的情况),XPath 表达式中的任何元素名称都必须以绑定到此默认命名空间的前缀作为前缀。通常通过使用特定方法/函数“注册默认名称空间”,以 XPath 的宿主语言执行绑定。

必须这样做的原因

只要 XPath 表达式中存在无前缀的名称,XPath 就会将该名称视为属于“无命名空间”。

以下是 XPath 1.0 W3C 规范的规范文本

节点测试中的 QName 使用表达式上下文中的命名空间声明扩展为扩展名称。这与 start 和 中元素类型名称的扩展方式相同。结束标记,但不使用使用 xmlns 声明的默认命名空间:如果 QName 没有前缀,则命名空间 URI 为 null(这与扩展属性名称的方式相同)。如果 QName 的前缀在表达式上下文中没有命名空间声明,则会出现错误”。

因此,在具有默认命名空间的文档上计算 /a/b/c 意味着:选择“无命名空间”中且名为 c 的所有元素,其父元素是位于“无命名空间”中的名为 b 的元素,其父元素是 xml 文档的顶部元素,其名为 a 且位于“无命名空间”中。

由于文档中的所有元素都位于其默认命名空间中,而不是“无命名空间”中,因此此 XPath 表达式不会选择任何内容

解决方案

  1. 在 XPath 引擎的 API 中,注册默认命名空间并为其绑定一个前缀(例如“x”)。

  2. 现在您可以而且必须使用此 XPath 表达式:/x:myrequest/x:state/x:value 而不是 /myrequest/state/value

This is the most FAQ on several XPath-related tags.

Whenever there is a default namespace in an XML document (as in your case), any element name in an XPath expression must be prefixed with a prefix that is bound to this default namespace. The binding is performed in the hosting language of XPath by typically "registering the default namespace" using a specific method/function.

The reason why this must be done:

Whenever there is an unprefixed name in an XPath expression, XPath treats this name as belonging to "no namespace".

Here is the normative text from the XPath 1.0 W3C Specification:

"A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded). It is an error if the QName has a prefix for which there is no namespace declaration in the expression context".

Therefore, evaluating /a/b/c on a document with a default namespace means: select all elements that are in "no namespace" and are named c, whose parent is an element named b that is in "no namespace", whose parent is the top element of the xml document and it is named a and is in "no namespace".

As all elements in the document are in its default namespace, and not in "no namespace", this XPath expression selects nothing.

Solution:

  1. In the API of your XPath engine, register the default namespace and bind to it a prefix (say "x").

  2. Now you can and must use this XPath expression: /x:myrequest/x:state/x:value instead of /myrequest/state/value

有深☉意 2024-11-07 13:54:56

使用 XPath 1.0 选择命名空间中的元素,您需要在 XPath 表达式中使用前缀来限定元素名称。因此,即使 XML 被清理为在 XPath 表达式中不使用前缀而是使用默认名称空间声明,您也需要使用绑定到您拥有的默认名称空间的前缀 (http://www.mywebsite.com/ xml/webservice)。如何将前缀绑定到命名空间 URI 取决于您使用的 XPath API,我对 JDOM 不熟悉,请自行检查其 API 以了解如何将前缀绑定到命名空间 URI。

[编辑]该方法是 http://www.jdom.org/docs/apidocs/org/jdom/xpath/XPath.html#addNamespace%28java.lang.String,%20java.lang.String%29 。因此,选择您喜欢的任何前缀(例如“pf”)并执行 addNamespace("pf", "http://www.mywebsite.com/xml/webservice"),然后在您的XPath(例如“pf:myrequest/pf:state/pf:value”)。

With XPath 1.0 to select elements in a namespace you need to use a prefix in your XPath expression to qualify element names. So even with the XML being cleaned up to not use a prefix but rather a default namespace declaration in your XPath expression you need to use a prefix bound to the default namespace you have (http://www.mywebsite.com/xml/webservice). How you bind a prefix to a namespace URI depends on the XPath API you use, I am not familiar with JDOM, check its API yourself on how to bind prefixes to namespace URIs.

[edit]The method is http://www.jdom.org/docs/apidocs/org/jdom/xpath/XPath.html#addNamespace%28java.lang.String,%20java.lang.String%29. so choose any prefix you like (e.g. "pf") and do addNamespace("pf", "http://www.mywebsite.com/xml/webservice"), then use that prefix in your XPath (e.g. "pf:myrequest/pf:state/pf:value").

ぃ弥猫深巷。 2024-11-07 13:54:56

我的问题是我必须使用
如果我想使用 Xpath 需要前缀吗?不是
仅命名空间就足够了?

如果您想使用 XPath,则不必使用名称空间前缀。仅命名空间就足够了,但如果您注册并使用命名空间前缀,它会使您的 XPath 更加简洁、更易于阅读和维护。

可以使用具有元素通用匹配的 XPath(即 *)以及指定 local-name()< 的谓词过滤器。 /code> 和 namespace-uri() 标准,如下所示:

/*[local-name()='myrequest' 
   and namespace-uri()='http://www.mywebsite.com/xml/webservice'] 
    /*[local-name()='state' 
       and namespace-uri()='http://www.mywebsite.com/xml/webservice']
      /*[local-name()='value' 
         and namespace-uri()='http://www.mywebsite.com/xml/webservice']

但是,注册命名空间并在 XPath 中使用命名空间前缀要容易得多。(例如/ws:myrequest/ws:state/ws:value )

My question is do I have to use a
prefix if I want to use Xpath? isnt
just namespace is enough?

You don't have to use a namespace prefix if you want to use XPath. Just the namespace is enough, but it makes your XPath much more concise, easier to read and maintain if you register and use a namespace prefix.

You could use an XPath with generic matches for elements (i.e. *) with predicate filters that specify the local-name() and namespace-uri() criteria, like this:

/*[local-name()='myrequest' 
   and namespace-uri()='http://www.mywebsite.com/xml/webservice'] 
    /*[local-name()='state' 
       and namespace-uri()='http://www.mywebsite.com/xml/webservice']
      /*[local-name()='value' 
         and namespace-uri()='http://www.mywebsite.com/xml/webservice']

However, it's much easier to register the namespace and use a namepace-prefix in your XPath.(e.g. /ws:myrequest/ws:state/ws:value )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文