xml 用于选择具有公共属性的所有节点的 XPath 表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4001277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:21:53  来源:igfitidea点击:

XPath expression for selecting all nodes with a common attribute

xmlxpath

提问by Hyman

a book I'm reading on XML says that to select all nodes in an XML file that have a specific attribute, use the syntax:

我正在阅读的一本关于 XML 的书说要选择 XML 文件中具有特定属性的所有节点,请使用以下语法:

//*/@_attribute_

What I don't understand is why the asterisk is needed. As I understand it, the expression // selects all descendants of the root node. So, wouldn't //@lang, for example, select all descendants of the root node that have an attribute called "lang"? I can't even interpret what the asterisk even means in the above expression (I know the asterisk in general means "all"). If someone could break it down for me I'd really appreciate it.

我不明白的是为什么需要星号。据我了解,表达式 // 选择根节点的所有后代。那么,例如,//@lang 不会选择具有名为“lang”的属性的根节点的所有后代吗?我什至无法解释上面表达式中星号的含义(我知道星号通常意味着“全部”)。如果有人可以为我分解它,我会非常感激。

Thanks

谢谢

回答by

Hi, a book I'm reading on XML says that to select all nodes in an XML file that have a specific attribute, use the syntax:

//*/@attribute

嗨,我正在阅读的一本关于 XML 的书说要选择 XML 文件中具有特定属性的所有节点,请使用以下语法:

//*/@attribute

That's wrong. It will be expanded to:

那是错误的。它将扩展为:

/descendant-or-self::node()/child::*/attribute::attribute

Meaning: All attributeattributes of any element child of a node being the root document itself or one of its descendats

含义:节点的任何元素子元素的所有attribute属性都是根文档本身或其后代之一

You need:

你需要:

/descendant::*[attribute::attribute]

Or the abbreviated form

或者缩写形式

//*[@attribute]

About the *: formaly is a name testnot a node type test. In XPath 1.0 there is no element type test. In XPath 2.0 you have element(). So, why select only elements? Well, it doesn't. The axis have a principal node type, from http://www.w3.org/TR/xpath/#node-tests:

关于*:正式是名称测试而不是节点类型测试。在 XPath 1.0 中没有元素类型测试。在 XPath 2.0 中,您有element(). 那么,为什么只选择元素呢?好吧,它没有。该轴有一个主要节点类型,来自http://www.w3.org/TR/xpath/#node-tests

Every axis has a principal node type. If an axis can contain elements, then the principal node type is element; otherwise, it is the type of the nodes that the axis can contain. Thus,

  • For the attribute axis, the principal node type is attribute.
  • For the namespace axis, the principal node type is namespace.
  • For other axes, the principal node type is element.

每个轴都有一个主节点类型。如果轴可以包含元素,则主节点类型为元素;否则,它是轴可以包含的节点的类型。因此,

  • 对于属性轴,主要节点类型是属性。
  • 对于命名空间轴,主要节点类型是命名空间。
  • 对于其他轴,主要节点类型为元素。

That's why *,child::*,self::*,descendant::*, etc. selects elements, but @*or attribute::*or namespace::*selects attributes or in scope namespaces.

这就是为什么*, child::*, self::*, descendant::*, 等选择元素,但@*orattribute::*namespace::*选择属性或作用域命名空间。

About predicate (the [@attribute]part): this expression is evaluate with each of the nodes selects by last step. It expects a boolean value for filtering. The boolean value for a node set (this is the result for attribute::attribute) is false for an empty node set, and true otherwise.

关于谓词([@attribute]部分):这个表达式是用最后一步选择的每个节点计算的。它需要一个布尔值进行过滤。节点集的布尔值(这是 的结果attribute::attribute)对于空节点集为 false,否则为 true。

回答by Dimitre Novatchev

The title of this question is:

这个问题的标题是

XPath expression for selecting all nodes with a common attribute

用于选择具有公共属性的所有节点的 XPath 表达式

However nowhere does the text of the question discuss how tho find all nodes that have a common attribute -- so the title may be incorrect.

然而,问题的文本没有讨论如何找到具有共同属性的所有节点——所以标题可能不正确。

To find all nodes that have a common attribute named x(BTW, only element-nodes can have attributes), use:

要查找具有名为x(顺便说一句,只有元素节点可以具有属性)的公共属性的所有节点,请使用

//*[@x]

Use:

使用

//@x

to select all attributes named xin the XML document. This is probably the shortest expression to do so.

选择x在 XML 文档中命名的所有属性。这可能是这样做的最短表达式。

There is nothing wrong with:

没有错

//*/@x

except that it is slightly longer.

除了它稍微长一点。

It is a shorthand for:

它是 的简写

/descendant-or-self::node()/child::*/attribute::x

and also selects all xattributes in the XML document.

并选择xXML 文档中的所有属性。

Someone may think that this expression doesn't select the xattribute of the top element in the document. This is a wrong conclusion, because the first location step:

可能有人认为这个表达式并没有选择x文档中顶部元素的属性。这是一个错误的结论,因为第一个定位步骤:

/descendant-or-self::node()

selects every nodein the document, including the root(/) itself.

选择文档中的每个节点,包括( /) 本身。

This means that:

这意味着:

/descendant-or-self::node()/child::*

selects every element, including the top element (which is the only child of the root node in a well-formed XML document).

选择每个元素,包括顶部元素(它是格式良好的 XML 文档中根节点的唯一子元素)。

So, when the last location step /@xis finally added, this will select all the xattributes of all nodes selected so far by the first two location steps -- that is all xattributes of all element-nodes in the XML document.

因此,当/@x最后添加最后一个定位步骤时,这将选择x前两个定位步骤迄今为止选择的所有节点的所有x属性——即XML 文档中所有元素节点的所有属性。