XPath通过嵌套选择节点(大多数嵌套节点减1)

时间:2015-12-14 09:48:03

标签: c# xml xpath nodes treenode

这是给出的xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Root>
    <WorkItem>
        <Id>716</Id>
        <WorkItemType>Product Backlog Item</WorkItemType>
        <TreeLevel>0</TreeLevel>
        <Children>
            <WorkItem>
                <Id>717</Id>
                <WorkItemType>Product Backlog Item</WorkItemType>
                <TreeLevel>1</TreeLevel>
                <Children>
                    <WorkItem>
                        <Id>719</Id>
                        <WorkItemType>Product Backlog Item</WorkItemType>
                        <TreeLevel>2</TreeLevel>
                        <Children>
                            <WorkItem>
                                <Id>721</Id>
                                <WorkItemType>Task</WorkItemType>
                                <TreeLevel>3</TreeLevel>
                                <Children />
                            </WorkItem>
                        </Children>
                    </WorkItem>
                    <WorkItem>
                        <Id>720</Id>
                        <WorkItemType>Product Backlog Item</WorkItemType>
                        <TreeLevel>2</TreeLevel>
                        <Children>
                            <WorkItem>
                                <Id>724</Id>
                                <WorkItemType>Task</WorkItemType>
                                <TreeLevel>3</TreeLevel>
                                <Children />
                            </WorkItem>
                        </Children>
                    </WorkItem>
                    <WorkItem>
                        <Id>723</Id>
                        <WorkItemType>Task</WorkItemType>
                        <TreeLevel>2</TreeLevel>
                        <Children>
                            <WorkItem>
                                <Id>744</Id>
                                <WorkItemType>Task</WorkItemType>
                                <TreeLevel>3</TreeLevel>
                                <Children>
                                    <WorkItem>
                                        <Id>747</Id>
                                        <WorkItemType>Task</WorkItemType>
                                        <TreeLevel>4</TreeLevel>
                                        <Children />
                                    </WorkItem>
                                </Children>
                            </WorkItem>
                        </Children>
                    </WorkItem>
                    <WorkItem>
                        <Id>748</Id>
                        <WorkItemType>Task</WorkItemType>
                        <TreeLevel>2</TreeLevel>
                        <Children />
                    </WorkItem>
                    <WorkItem>
                        <Id>752</Id>
                        <WorkItemType>Product Backlog Item</WorkItemType>
                        <TreeLevel>2</TreeLevel>
                        <Children>
                            <WorkItem>
                                <Id>753</Id>
                                <WorkItemType>Product Backlog Item</WorkItemType>
                                <TreeLevel>3</TreeLevel>
                                <Children />
                            </WorkItem>
                        </Children>
                    </WorkItem>
                </Children>
            </WorkItem>
            <WorkItem>
                <Id>718</Id>
                <WorkItemType>Task</WorkItemType>
                <TreeLevel>1</TreeLevel>
                <Children />
            </WorkItem>
        </Children>
    </WorkItem>
</Root>

简化xml就像这样

716 (PBI) Root
  - 717 (PBI)
    - 719 (PBI)
      - 721 (Task)
    - 720 (PBI)
      - 724 (Task)
    - 723 (Task)
      - 744 (Task)
        - 747 (Task)
    - 748 (Task)
    - 752 (PBI)
      - 753 (PBI)
  - 718 (Task)

我想检索WorkItemType“Product Backlog Item”的所有第二个内部节点。 我还可以说我希望“Product Backlog Items”具有类型为“Product Backlog Item”的子元素,但没有“Product Backlog Item”的子元素元素。

在给定的例子中,这将是

我尝试使用此xpath命令接收它(我在C#中使用System.Xml.XmlDocument):

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

为了更好的可读性

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

使用此XPath表达式,我得到ID为716,717和752的项目。

但我只想要项目 752。

1 个答案:

答案 0 :(得分:0)

我们并不确切知道XML文档的结构有多少变化,但尝试从完全不同的角度来看待它。

从最里面的WorkItem开始,该WorkItemType = 'Product Backlog Item'具有元素WorkItem,但没有任何子parent::元素。然后,使用//WorkItem[WorkItemType = 'Product Backlog Item' and not(Children/WorkItem)]/parent::Children/parent::WorkItem 轴向后工作。

完整的XPath表达式看起来像

<WorkItem>
    <Id>752</Id>
    <WorkItemType>Product Backlog Item</WorkItemType>
    <TreeLevel>2</TreeLevel>
    <Children>
        <WorkItem>
            <Id>753</Id>
            <WorkItemType>Product Backlog Item</WorkItemType>
            <TreeLevel>3</TreeLevel>
            <Children/>
        </WorkItem>
    </Children>
</WorkItem>

,唯一的结果是

WorkItem

请注意,上面的表达式要求内部WorkItem不包含任何其他//WorkItem[WorkItemType = 'Product Backlog Item' and not(Children/WorkItem[WorkItemType = 'Product Backlog Item'])]/parent::Children/parent::WorkItem 元素 - 这不是您所要求的。如果我要密切关注你的描述,这将引导我

WorkItem

还包括ID为717的{​​{1}}。