删除前缀时,XPath返回null

时间:2011-04-10 16:04:34

标签: java xml xpath xsi

我在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中为每个节点收到空。

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

3 个答案:

答案 0 :(得分:3)

这是几个与XPath相关的标签上最常见的常见问题

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

之所以必须这样做

只要XPath表达式中有一个没有前缀的名称,XPath就会将此名称视为属于“no namespace”。

以下是 XPath 1.0 W3C Specification

中的规范性文字

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

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

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

<强>解决方案

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

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

答案 1 :(得分:2)

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

[edit]该方法为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”)。

答案 2 :(得分:1)

  

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

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

可以 使用带有通用匹配项的XPath(即*),其谓词过滤器指定local-name()和{{1标准,像这样:

namespace-uri()

但是,注册命名空间并在XPath中使用名称空间前缀要容易得多(例如/*[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']