这是我给出的XML:
<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>
<Id>722</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>4</TreeLevel>
<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>
<TreeLevel>3</TreeLevel>
<Children>
<WorkItem>
<Id>726</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>4</TreeLevel>
<Children />
</WorkItem>
</Children>
</WorkItem>
<WorkItem>
<Id>725</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>3</TreeLevel>
<Children>
<WorkItem>
<Id>727</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>4</TreeLevel>
<Children />
</WorkItem>
<WorkItem>
<Id>728</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>4</TreeLevel>
<Children />
</WorkItem>
<WorkItem>
<Id>729</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>4</TreeLevel>
<Children>
<WorkItem>
<Id>745</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>5</TreeLevel>
<Children />
</WorkItem>
<WorkItem>
<Id>746</Id>
<WorkItemType>Task</WorkItemType>
<TreeLevel>5</TreeLevel>
<Children />
</WorkItem>
</Children>
</WorkItem>
</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>
</Children>
</WorkItem>
</Children>
</WorkItem>
我想检索节点的所有节点,其子节点有两种特定类型。如果这种类型是一种,我也希望得到所有的后代。
我尝试使用此xpath命令接收它(我在C#中使用System.Xml.XmlDocument):
xmlDoc.SelectNodes("Children/WorkItem[WorkItemType[text()='Product Backlog Item']]|Children/WorkItem[WorkItemType[text()='Task']]/following::WorkItem[WorkItemType[text()='Task']]");
// splitted for better readability
Children/WorkItem[
WorkItemType[
text()='Product Backlog Item']
]|
Children/WorkItem[
WorkItemType[
text()='Task']
]/following::WorkItem[WorkItemType[text()='Task']]
这仅为我提供ID为719和720的节点。 但我希望WorkItem节点的Id为:719和720(xpath表达式的第一部分)以及723和744(来自第二个xpath表达式)。
如何在XPath中表达这一点?
在给定的XML中,我期望ID为719,720,723,744的WorkItem元素
答案 0 :(得分:0)
目前还不清楚你想要实现什么,但我会尽力向你展示一个可能的解决方案来处理这项任务。
在我看来,它并没有创造出一个巨大的XPath表达,因为在几年之后它真的很难理解。对于您的情况,在一个XPath表达式中无法获得所需的一切。你可以分开它:
foreach (var element in xmlDoc.SelectNodes("WorkItem/Children").OfType<XmlElement>())
{
var elements = element.SelectNodes("WorkItem[WorkItemType[text()='Product Backlog Item' or text()='Task']]");
foreach(var child in elements.OfType<XmlElement>())
Process(child);
}
public void Process(XmlElement rootElement)
{
// Print some info about the work item
// ...
foreach (var element in rootElement.SelectNodes("Children").OfType<XmlElement>())
{
// I'm not sure whether it's exactly what you want but you can
// easily change this expression.
var children = element.SelectNodes("WorkItem[WorkItemType[text()='Task']]");
// continue the processing of children
foreach (var child in children.OfType<XmlElement>())
Process(child);
}
}
首先,检查根子项的WorkItems的所有节点,然后将它们发送到Process
方法,该方法也称为内部(递归)。它将帮助您处理更深层次的结构。
答案 1 :(得分:0)
我找到了一个适用于我想做的xpath:
Children/WorkItem[WorkItemType[text()='Product Backlog Item']]|Children/WorkItem[WorkItemType[text()='Task']]/descendant-or-self::WorkItem[WorkItemType[text()='Task']]
为了更好的可读性
Children/WorkItem[WorkItemType[
text()='Product Backlog Item']
]|
Children/WorkItem[WorkItemType[
text()='Task']
]/descendant-or-self::WorkItem[WorkItemType[
text()='Task']]