我正在开发的应用程序接收类似于以下的XML结构:
<Root>
<Valid>
<Child name="Child1" />
<Container>
<Child name="Child2" />
</Container>
<Container>
<Container>
<Child name="Child3"/>
<Child name="Child4"/>
</Container>
</Container>
<Wrapper>
<Child name="Child5" />
</Wrapper>
<Wrapper>
<Container>
<Child name="Child19" />
</Container>
</Wrapper>
<Container>
<Wrapper>
<Child name="Child6" />
</Wrapper>
</Container>
<Container>
<Wrapper>
<Container>
<Child name="Child20" />
</Container>
</Wrapper>
</Container>
</Valid>
<Invalid>
<Child name="Child7" />
<Container>
<Child name="Child8" />
</Container>
<Container>
<Container>
<Child name="Child9"/>
<Child name="Child10"/>
</Container>
</Container>
<Wrapper>
<Child name="Child11" />
</Wrapper>
<Container>
<Wrapper>
<Child name="Child12" />
</Wrapper>
</Container>
</Invalid>
</Root>
我需要在以下条件下获取Child元素列表:
其中m,n,o是自然数。
我需要编写以下XPath表达式
Valid/Child
Valid/Container/Child
Valid/Container/Container/Child
Valid/Container/Container/Container/Child
...
作为单个 XPath表达式。
对于提供的示例,XPath表达式仅返回名称元素,其名称属性等于 Child1 , Child2 , Child3 和 Child4 。
我最接近解决方案的是表达式。
Valid/Child | Valid//*[self::Container]/Child
但是,这会选择儿童元素,名称属性等于 Child19 和 Child20 。
XPath语法是否支持可选的元素出现或者在前面的示例中为self Child 和 Valid 元素之间的所有祖先设置类似于self的条件?
答案 0 :(得分:4)
使用强>:
//Child[ancestor::*
[not(self::Container)][1]
[self::Valid]
]
在提供的XML文档上评估此XPath表达式时:
<Root>
<Valid>
<Child name="Child1" />
<Container>
<Child name="Child2" />
</Container>
<Container>
<Container>
<Child name="Child3"/>
<Child name="Child4"/>
</Container>
</Container>
<Wrapper>
<Child name="Child5" />
</Wrapper>
<Wrapper>
<Container>
<Child name="Child19" />
</Container>
</Wrapper>
<Container>
<Wrapper>
<Child name="Child6" />
</Wrapper>
</Container>
<Container>
<Wrapper>
<Container>
<Child name="Child20" />
</Container>
</Wrapper>
</Container>
</Valid>
<Invalid>
<Child name="Child7" />
<Container>
<Child name="Child8" />
</Container>
<Container>
<Container>
<Child name="Child9"/>
<Child name="Child10"/>
</Container>
</Container>
<Wrapper>
<Child name="Child11" />
</Wrapper>
<Container>
<Wrapper>
<Child name="Child12" />
</Wrapper>
</Container>
</Invalid>
</Root>
确切地选择了所需节点:
<Child name="Child1"/>
<Child name="Child2"/>
<Child name="Child3"/>
<Child name="Child4"/>
<强>解释强>:
表达式:
//Child[ancestor::*
[not(self::Container)][1]
[self::Valid]
]
表示强>:
从文档中的所有Child
元素中,仅选择那些非Container
的第一个祖先为Valid
的元素。
答案 1 :(得分:3)
//Valid
//Child[count(ancestor::Container[ancestor::Valid])
= count(ancestor::*[ancestor::Valid])]
说明:
//Valid//Child
返回作为Child
个节点后代的所有Valid
个节点。
count(ancestor::Container[ancestor::Valid]])
返回当前节点(Container
)的祖先Child
标记的数量,并且它们自己有一个名为Valid
的祖先
count(ancestor::*[ancestor::Valid])
返回当前节点(Child
)祖先的所有标记的数量,并且它们自己有一个名为Valid
的祖先
因此,如果Valid
和Child
之间的所有代码都被称为Container
,则两个值相等。
但是,此表达式假定不会有任何嵌套的Valid
标记,即{}不会接受/Valid/Valid/Child
。
更新:再次查看您的xml,这会不会更容易?
//Valid//Child[not(ancestor::Wrapper)]