在XPath表达式中声明命名空间

5
我的应用程序需要对一些XML数据执行XPath表达式。表达式由用户在运行时提供。因此,我无法创建XmlNamespaceManager并传递给XPathEvaluate,因为我不知道编译时的前缀和名称空间。
有没有可能在xpath表达式中指定命名空间声明?
评论回答:
1. XML数据具有一个默认命名空间,但可以有任何命名空间的嵌套元素。用户知道他所处理的数据的名称空间。 2. 用户提供的xpath表达式将针对许多XML文档进行评估,并且每个文档可以为相同的命名空间使用其自己的前缀。

目标 XML 文档中是否有多个命名空间?您是否控制其内容或是由用户提供的? - Rich Tebb
请看问题,我已经在那里回答了。 - Anthony Serdyukov
你写道:“我无法创建XmlNamespaceManager以传递给XPathEvaluate,因为我不知道编译时的前缀和命名空间。”这是错误的。所有这些XPath可视化工具都可以轻松实现。 - user357812
我明白您的想法,@Alejandro: 在xpath表达式附近让用户指定命名空间和前缀。恐怕这可能是我要走的路。然而,我得出结论,没有办法使用xpath表达式声明命名空间。 - Anthony Serdyukov
是的,作为一种托管语言,XPath表达式无法更改XPath引擎调用上下文。这取决于宿主语言的功能。 - user357812
3个回答

6

如果相同的前缀可以绑定到不同的命名空间,且前缀未知,则唯一纯XPath指定此类表达式的方法是使用下面的元素引用形式::

someName[namespace-uri() = 'exactNamespace']

因此,一个特定的XPath表达式如下::

/*/a[namespace-uri() = 'defaultNS']/b[namespace-uri() = 'NSB']
                                         /c[namespace-uri() = 'defaultNS']

作为XPath Visualizer的作者,我认为您可以回答如何在运行时注册命名空间URI绑定... - user357812
@Alejandro:是的,但这不能在纯XPath中完成——我已经说过了。正如我们都知道的那样,在XPath之外,有许多方法可以做到这一点——这取决于所使用的特定XPath引擎和宿主语言。 - Dimitre Novatchev

2

我不知道如何在XPath表达式中定义命名空间前缀。

但是你可以使用local-name()和namespace-uri()函数来编写与命名空间前缀无关的XPath表达式。

或者,如果您预先知道XML命名空间,您可以在XmlNamespaceManager中注册一个任意的前缀,并告诉用户在XPath表达式中使用该前缀。无论XML文档本身是否注册了不同的前缀或没有前缀,路径解析都基于命名空间而不是前缀。

另一种选择是在运行时扫描文档(如果您尚未加载它,请使用XmlReader以获得低资源开销),然后将使用的映射添加到XmlNamespaceManager中的文档中。我不确定您是否可以从XmlDocument中获取命名空间和前缀,但我看不到直接的方法来做到这一点。但是通过XmlReader很容易实现,因为它为每个节点公开NamespaceURI和Prefix成员。


@TToni:非常有趣!不幸的是,用户提供的XPath表达式需要针对许多XML文档进行评估,并且不能保证每个文档都使用相同的前缀。 - Anthony Serdyukov
@Anton:那么用户如何决定在她的XPath中使用什么前缀呢?如果她尝试基于一个文档使用前缀,除非为所有文档提供一致的前缀/命名空间映射,否则她的路径将在另一个文档上无用。如果这也不可能,用户将不得不在没有前缀的情况下工作。 - TToni
@TToni,用户肯定知道命名空间。她可以使用任何前缀。你自己说过:“路径解析仅基于命名空间,而不基于前缀。” - Anthony Serdyukov
@Anton:更正一下,她可以使用任何你定义的命名空间前缀。因此,如果她想要使用前缀,你们必须就如何进行映射达成某种协议。你可以预先扫描文档并告诉她,或者也许你事先知道一些命名空间,对于这些命名空间,你可以定义众所周知的前缀,而对于其他命名空间,她必须在没有前缀的情况下工作,或者采用任何组合。有几个选项可供选择,你必须选择最可行的选项。 - TToni
接受作为最完整的答案。 - Anthony Serdyukov
显示剩余3条评论

2
有没有可能在xpath表达式中指定命名空间声明?
答案是否定的 - 它总是在调用环境中完成的(实际上更灵活)。
另一种选择是使用XQuery,它允许在查询前言中声明命名空间。
更新(2020)
在XPath 3.1中,您可以使用语法`/*/Q{http://my-namespace}a`。
不幸的是,如果您仍在使用Microsoft软件,则自2011年以来情况并未改变 - 您仍然被困在具有所有缺点的XPath 1.0中。

XQuery的prolog正是我梦寐以求的。但是我还没有在.NET中找到内置的XQuery功能。 - Anthony Serdyukov
@Anton:在这种情况下,XQSharp (http://www.xqsharp.com/xqsharp/about.htm) 可能是另一个选择。 - TToni
我已经搜索了XQuery的实现。由于其许可证问题,XQsharp不是一个选择。 - Anthony Serdyukov
公平地说,只有在您可以访问和控制调用环境时,它才更加灵活。如果您只能提供XPath但没有命名空间(显然是一种糟糕的设计,但不幸的是,企业软件),则XPath会变得非常混乱,而如果支持XPath prolog声明,则会更好。 - brianary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接