2

我在 Eclipse 下的 Java 中使用 XPath。我正在编写一个肥皂网络服务,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 查询它时,就像XPath.selectSingleNode()我总是从 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)));
4

3 回答 3

3

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

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

必须这样做的原因

只要 XPath 表达式中有一个不带前缀的名称,XPath 就会将此名称视为属于“无命名空间”。

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

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

因此,评估/a/b/c具有默认命名空间的文档意味着:选择“无命名空间”中的所有元素,c其父元素b是“无命名空间”中的命名元素,其父元素是 xml 文档的顶部元素它被命名a并位于“无命名空间”中。

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

解决方案

  1. 在您的 XPath 引擎的 API 中,注册默认命名空间并将前缀绑定到它(比如“x”)。

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

于 2011-04-10T16:30:44.270 回答
2

使用 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”)。

于 2011-04-10T16:29:16.780 回答
1

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

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

可以使用 XPath 对元素(即*)进行通用匹配,并使用指定local-name()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

于 2011-04-10T17:33:28.527 回答