XPath轴中的命名空间是什么?

3

我正在研究XPath轴,我已经理解以下所有轴:

'ancestor'(祖先)
| 'ancestor-or-self'(祖先或自身)
| 'attribute'(属性)
| 'child'(子代)
| 'descendant'(后代)
| 'descendant-or-self'(后代或自身)
| 'following'(后继兄弟节点)
| 'following-sibling'(后继同级节点)
| 'parent'(父节点)
| 'preceding'(前驱节点)
| 'preceding-sibling'(前驱同级节点)
| 'self'(自身)

我唯一不明白的是:

| 'namespace'(命名空间)

有没有人能给我一个好的例子和理解,说明'namespace'实际上是做什么用的?

例如:

打开:https://www.google.co.in/

或者

HTML代码

<a style="left:-1000em;position:absolute" href="/setprefs?suggon=2&prev=https://www.google.co.in/&sig=0_ujdR1PrGxEbi_EiD6RbIb4VvaXc%3D">Screen-reader users, click here to turn off Google Instant.</a>

我正在尝试以下xpath表达式

  //a[@style='left:-1000em;position:absolute']/namespace::*[name()='google']

我在上面的命名空间中做错了什么?

此外,我还想知道axes | 'attribute'的用途是什么。在哪种情况下它有帮助?


1
可能是XML中的“xmlns”是什么意思?的重复。 - Quentin
1
可能是重复的问题XML命名空间是如何工作的 - Quentin
1
可能是什么是XML命名空间?的重复问题。 - Quentin
谢谢,我会研究一下的。 - Shubham Jain
@Quentin - 他们都没有好的例子。 - Shubham Jain
显示剩余2条评论
2个回答

4
namespace:: 轴选择 命名空间节点。没有花哨的东西。
而根据链接规范,命名空间节点 包括以下内容:
  • 元素上每个名称以 xmlns: 开头的属性。

  • 祖先元素上每个名称以 xmlns: 开头的属性(除非元素本身或更近祖先重新声明了该前缀)。

  • 如果元素或某个祖先具有 xmlns 属性,并且最接近此类元素的 xmlns 属性的值非空,则会添加一个 xmlns 属性。

例如,给定以下 XML 元素:
<a xmlns:google="some namespace uri here"/>

下面的XPath表达式将返回xmlns:google属性[演示]
//a/namespace::*[name()='google']

这个例子对应上述第一个要点,因为 xmlns:google 是属性,它位于上下文元素 <a> 上,其名称以 xmlns: 开头。
attribute 轴的解释与此类似;它只是选择 XML 属性。
你可以将 attribute 轴视为 @ 的更长版本,而你已经在使用 @。例如,下面两个表达式意思相同:
//a[attribute::style='left:-1000em;position:absolute']
//a[@style='left:-1000em;position:absolute']

@ShubhamJain 也许你使用的XPath处理器没有实现“命名空间”轴?http://stackoverflow.com/a/11189061/2998271 - har07
是的,我的意思是在元素谓词中使用namespace::轴。对我来说也不起作用。我正在测试Oxygen Author 17.1、XPath 1.0和XPath 2.0。@har07,请描述一下你的技术场景,好吗? - Honza Hejzl
谢谢,我可以确认它有效。然而,它仅在命名空间直接声明为元素属性时才有效。如果它在根元素中声明为默认命名空间或者在根元素中声明并用作前缀,则无法工作。我认为没有干净的解决方案。有趣的是,最初的问题是一个典型的XY问题,我们试图回答Y,但需要X。尽管如此,这是一个有用的问题。 - Honza Hejzl
1
@HonzaHejzl,你提供的XPath没有返回结果的原因与谓语中的“命名空间”无关。这是因为<a>现在继承了默认命名空间,所以即使只有//a也不会返回任何结果。将你的XPath与这个进行比较://*[local-name()='a' and namespace::*='some namespace uri here'] - har07
1
我可以在答案中使用那个吗?只是为了完整起见?你说得对,谢谢,好的课程! - Honza Hejzl
显示剩余8条评论

2

根据逻辑,它应该选择与命名空间相关的所有元素。然而,它的行为有点更加复杂,因此很少使用。(在XPath 2.0中被视为已弃用。)

<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
    <BASE xmlns:base="http://www.tei-c.org/ns/1.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
        <base:p>XXX</base:p>
        <dc:p>yyy</dc:p>
    </BASE>
    <NEXT xmlns="http://purl.org/dc/elements/1.1/">
        <p>zzz</p>
    </NEXT>
</ROOT>

XPath (2.0):

//*[namespace::dc]

选择整个 BASE 元素。它类似于:

//*[namespace-uri-for-prefix('dc', .)]

在XPath 1.0中无法使用该功能。

//*[namespace::*='http://purl.org/dc/elements/1.1/']

选择BASENEXT元素,这种用法被认为有点奇怪,不建议使用。

//*[local-name(.) eq 'p' and namespace::*='http://purl.org/dc/elements/1.1/']

选择所有的 p 元素,其中包括 base:pdc:p,以及 p 元素。
//*[local-name(.) eq 'p' and namespace::dc]

选择 BASE 元素的 base:pdc:p

//*[local-name(.) eq 'p' and namespace-uri() eq 'http://purl.org/dc/elements/1.1/']

选择所有绑定到URI的元素。这意味着这是最准确的选项。

或者可以尝试类似以下的内容:

//*[contains(namespace-uri(), 'purl')]

或者

//self::BASE/*[contains(namespace-uri(), 'purl')]

在 Oxygen Author 17.1 中测试通过

更新

根据您的需求,似乎您可能正在尝试选择带有字符串 googlehref 属性的元素,而不是特定命名空间的元素。那么 //a[contains(@href, 'google')] 怎么样?

更新 II

如评论所述,更新 是可行的解决方案。但是,我认为下面的信息也很有用:


谢谢你的回答。我在我的问题中添加了一个例子。你能帮我看一下并告诉我我做错了什么吗? - Shubham Jain
我已经发布了我的问题,如下所示:- HTML 代码<a style="left:-1000em;position:absolute" href="/setprefs?suggon=2&prev=https://www.google.co.in/&sig=0_ujdR1PrGxEbi_EiD6RbIb4VvaXc%3D">屏幕阅读器用户,请单击此处关闭 Google 即时搜索。</a> 我正在尝试下面的 xpath //a[@style='left:-1000em;position:absolute']/namespace::*[name()='google'] 我在上述命名空间中做错了什么? - Shubham Jain
请查看一下,告诉我这里我做错了什么。 - Shubham Jain
有趣的是,你可能正在尝试选择具有字符串“google”的href属性的元素,而不是特定命名空间中的元素。那么//a[contains(@href, 'google')]呢? - Honza Hejzl
:D .... 嗯,上面的 XPath 可以使用。其实我对轴是新手,只有命名空间对我不起作用。我想到一个主意。此外,它可能已经被弃用了,所以在我的 Firepath 中不能工作。非常感谢! :D - Shubham Jain

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