XPath按节点,子节点和子子节点条件选择节点

时间:2015-12-04 14:23:47

标签: xml xpath nodes treenode

我想检索应用了节点,子节点和子子节点条件的所有节点

我尝试使用此xpath命令接收它:

xmlDoc.SelectNodes("//WorkItem[WorkItemType[text()='Product Backlog Item'] and ./Childern/WorkItem/WorkItemType[text() = 'Task'] and /Childern/WorkItem/WorkItemType[text() != 'Product Backlog Item'] and ./Childern/WorkItem/WorkItemType[text() = 'Task']]");

这为我提供了无节点。但我希望WorkItem节点具有Id' s:719和720但不是717

如何在XPath中表达这一点?

给定的xml如下所示:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <id>716</id>
    <WorkItemType>Product Backlog Item</WorkItemType>
    <Children>
        <WorkItem>
            <id>717</id>
            <WorkItemType>Product Backlog Item</WorkItemType>
            <Children>
                <WorkItem>
                    <id>719</id>
                    <WorkItemType>Product Backlog Item</WorkItemType>
                    <Children>
                        <WorkItem>
                            <id>721</id>
                            <WorkItemType>Task</WorkItemType>
                            <Children>
                                <WorkItem>
                                    <id>722</id>
                                    <WorkItemType>Task</WorkItemType>
                                    <Children/>
                                </WorkItem>
                            </Children>
                        </WorkItem>
                    </Children>
                </WorkItem>
                <WorkItem>
                    <id>720</id>
                    <WorkItemType>Product Backlog Item</WorkItemType>
                    <TreeLevel>2</TreeLevel>
                    <Children>
                        <WorkItem>
                            <id>724</id>
                            <WorkItemType>Task</WorkItemType>
                            <Children>
                                <WorkItem>
                                    <id>726</id>
                                    <WorkItemType>Task</WorkItemType>
                                    <Children/>
                                </WorkItem>
                            </Children>
                        </WorkItem>
                    </Children>
                </WorkItem>
                <WorkItem>
                    <id>723</id>
                    <WorkItemType>Task</WorkItemType>
                    <Children>
                        <WorkItem>
                            <id>744</id>
                            <WorkItemType>Task</WorkItemType>
                            <Children/>
                        </WorkItem>
                    </Children>
                </WorkItem>
            </Children>
        </WorkItem>
    </Children>
</root>

更新

由于Rolf Rander的输入,我增加了一些解释:

  • 我想拥有WorkItemType的WorkItem元素&#39; Product Backlog Item&#39;它只有WorkItem-WorkItemType的元素&#39;任务&#39;像任何一种孩子(儿童,孙子孙女等......)。

在设计时,儿童所覆盖的水平有多深。我已经更新了我的问题。 (我纠正了我的错误Childern - &gt; xml文件中的儿童)。

2 个答案:

答案 0 :(得分:2)

您尝试实现的目标尚不完全清楚,但重新格式化代码似乎有几项还原剂测试:

//WorkItem[
WorkItemType[text()='Product Backlog Item'] and
./Childern/WorkItem/WorkItemType[text() = 'Task'] and
/Childern/WorkItem/WorkItemType[text() != 'Product Backlog Item'] and
./Childern/WorkItem/WorkItemType[text() = 'Task']
]

你测试&#34;等于&#39;任务&#39;&#34;两次,并且不应该检查它是否等于&#39;任务&#39;与产品待办事项项目&#39;。

不同

您可以查看&#34;任何子女或孙子女&#34; //,因此:

  • 任何WorkItem
  • 使用WorkItemType =&#39;产品待办事项项目&#39;和
  • 名称为WorkItemType且内容为&#39;任务&#39;
  • 的子项下没有节点

可以翻译成:

//WorkItem[
     WorkItemType[text()='Product Backlog Item'] and
     not(Children//WorkItemType[text() != 'Task'])
]

答案 1 :(得分:1)

而不是这个..

./Childern/WorkItem/WorkItemType[text() != 'Product Backlog Item']

使用这个:

not(./Childern/WorkItem/WorkItemType[text() = 'Product Backlog Item'])

前者评估为true,如果至少有一个WorkItemType符合条件(第一个文本节点子不等于'Product Backlog Item')。将其与后者进行对比,后者仅在true符合条件时评估为WorkItemType(具有第一个文本节点子等于'Product Backlog Item')。< / p>

所以完整的XPath看起来像这样(为了可读性而格式化):

//WorkItem[
    WorkItemType[text()='Product Backlog Item'] 
        and 
    ./Childern/WorkItem/WorkItemType[text() = 'Task'] 
        and 
    not(./Childern/WorkItem/WorkItemType[text() = 'Product Backlog Item']) 
        and 
    ./Childern/WorkItem/WorkItemType[text() = 'Task']
]

<强>更新

在回答更新后的问题时,我会做这样的事情:

//WorkItem[WorkItemType[text()='Product Backlog Item']]
          [not(.//WorkItem/WorkItemType/text() != 'Task')]