1

我正在使用 Java 自学来自Pro XML Development 的XPath 。只是为了练习,我构建了一个示例 XML 文档和一些 XPath 表达式。
下面是一些 XPath 表达式及其解释和一些相关问题。如果我的解释有误,请纠正我,并在适用的情况下回答问题。

XML

<?xml version="1.0" encoding="UTF-8" ?>
<people>
    <student scholarship="Yes">
        <name>John</name>
        <course>Computer Technology</course>
        <semester>6</semester>
        <scheme>E</scheme>
    </student>

    <student>
        <name>Foo</name>
        <course>Industrial Electronics</course>
        <semester>6</semester>
        <scheme>E</scheme>
    </student>

    <grumpy-cat>
        <soup-noodle>
            <student>
                <name>Dingle</name>
                <course>Grumpiness</course>
                <semester>3</semester>
                <scheme>E</scheme>
            </student>
        </soup-noodle>
    </grumpy-cat>
</people>  

表达式 1: /people/student[@scholarship='Yes']/name
解释:将选择<name>..</name>包含在其中的元素,<people>该元素具有名为值<student>的属性问题:这是否也会选择其中的值 John ???? scholarshipYes

表达式2: /people/student[2]
解释:将选择元素<student>..</student>中位于第二位置的元素<people>
问题:它是否还会选择其中的子节点?

表达式3: /people/student/@scholarship
说明:将在元素student中选择属性奖学金。如果有多个<student scholarship="">,那么它将选择多个属性

表达式 4: //name[ancestor::student]
解释:将选择所有<name>..</name>元素
//意味着“所有的后代”。在我的上下文中,这意味着“只要我的直系祖先是学生,我不在乎后代是谁”

4

2 回答 2

2

所有四个 XPath 表达式都选择输入树中的节点,如果您使用 XPath 1.0,则此类 XPath 表达式返回一组节点(其中该集可以为空或包含输入树的一个或多个节点),如果您使用 XPath 2.0 此类表达式返回一系列节点(也可以是空的,也可以包含输入树的一个或多个节点)。

  1. 您的第一个表达式name在给定的输入树中选择一个元素节点,该节点包含一个值为 的文本节点John
  2. 您的第二个表达式student在输入树中选择一个元素节点,该student元素节点有几个子节点(XPath 选择只是在输入树中选择一个节点,它不会修改任何内容或创建新节点)。
  3. 您的第三个表达式选择一个scholarship属性节点,如果输入 XML 包含多个具有属性的student元素节点,您是对的,它会选择几个这样的节点。scholarship
  4. 您的第四个表达式//name[ancestor::student]是一个缩写形式(参见http://www.w3.org/TR/xpath/#path-abbrev),/descendant-or-self::node()/name[ancestor::student]它是/descendant-or-self::node()/child::name[ancestor::student]. 因此它选择根节点的所有name子元素以及根节点的所有后代节点,其中name元素具有student祖先元素节点。您对该表达式的解释是错误的,关于all the descendants(这至少是不精确的)以及my immediate ancestor is student. 直接祖先是父级,在您查找所有级别的祖先时简单地parent::student用 XPath表示。ancestor::student而所有的后代都是/descendant::name。另一方面,定义了方式,//下一步归结为与name//name/descendant::name.
于 2013-05-12T14:23:24.863 回答
2

表达式 1:/people/student[@scholarship='Yes']/name 解释: 将选择包含在其中的元素 .. 具有名为 Scholarship 且值为 Yes 的属性 问题:这是否也会选择其中的值 John ????

此表达式选择任何(所有)name元素,它是元素的子student元素(其scholarship属性的字符串值为字符串“yes”)并且是peopleXML 文档的顶部元素(名为 )的子元素。XPath 不选择“值”——它选择节点。在这种情况下,字符串“John”是所选name元素的字符串值。所选name元素有一个子文本节点,其字符串值为“John”。

表达式 2:/people/student[2] 解释:将选择元素中的第 2 个位置的元素 .. 问题:它是否也会选择其中的子节点?

student这将选择顶部元素(其名称必须为)的第二个(按文档顺序)子元素people。所选元素的子节点本身不会被选中。可以使用以下count()函数获得所选节点的数量:

count(/people/student[2])

它是1——这意味着只有元素(而不是它的子元素或后代)被选中。

表达式3:/people/student/@scholarship 说明:将选择元素student中的属性scholarship。如果有多个,那么它将选择多个属性

这将选择作为顶部元素(其名称必须为 )的子元素scholarship的任何元素的属性。这意味着如果有 N个元素是顶部元素的子元素,并且每个元素都有一个属性,则将选择 N 个奖学金属性。studentpeoplestudentpeoplescholarship

表达式 4://name[ancestor::student] 解释:将选择所有 .. 元素 // 表示“所有后代”。在我的上下文中,这意味着“只要我的直系祖先是学生,我不在乎后代是谁”

这将选择所有name具有student祖先的元素(并且此祖先可能不仅是直接父级,而且是直接父级的祖先)。

这里可以编写一个不包含任何反向轴的等效 XPath 表达式:

//student//name

如果您想选择name其父元素是元素的所有元素student,一种表达方式是:

//student/name

最后,我建议使用像XPath Visualizer(我在 12 年前创建的)这样的工具,它帮助成千上万的人通过玩耍和玩乐来学习 XPath

于 2013-05-12T17:23:07.403 回答