Xml 基于元素值获取ancester节点的Xpath查询
我试图找到所有遵循以下两条规则的元素名 一,。元素应具有擦除功能 2.如果两个或多个元素在层次结构Ex:中都有erase,并且都有erase,那么在这种情况下,只有父节点名必须是printedie 因此,以下xml所需的结果需要是: b,y,p 输出:Xml 基于元素值获取ancester节点的Xpath查询,xml,xslt,xpath,xml-parsing,Xml,Xslt,Xpath,Xml Parsing,我试图找到所有遵循以下两条规则的元素名 一,。元素应具有擦除功能 2.如果两个或多个元素在层次结构Ex:中都有erase,并且都有erase,那么在这种情况下,只有父节点名必须是printedie 因此,以下xml所需的结果需要是: b,y,p 输出: a.b a.b.d a.e.y a.e.z.p 有谁能帮我找出只产生a.b、a.e.y和a.e.z.p的查询 如果你需要更多的细节,请告诉我。或任何其他用例。以下XPath选择您想要的节点: //*[set[text()='erase']][n
a.b
a.b.d
a.e.y
a.e.z.p
有谁能帮我找出只产生a.b、a.e.y和a.e.z.p的查询
如果你需要更多的细节,请告诉我。或任何其他用例。以下XPath选择您想要的节点:
//*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]
我用下面的样式表测试了它
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="@*|text()" />
<xsl:template match="//*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]">
<xsl:text>(</xsl:text>
<xsl:for-each select="self::*|ancestor::*">
<xsl:value-of select="name()"/>
<xsl:text>.</xsl:text>
</xsl:for-each>
<xsl:text>) </xsl:text>
</xsl:template>
</xsl:stylesheet>
还是哈波回答的这个小问题
*[set[text()='erase']][ancestor::*[set[text()!='erase']]]
<>我对Novatchev的回答的评论后,请考虑有用的测试用例:
这是对提问者演示文档的更改。我添加了另一个节点
<?xml version="1.0"?>
<a>
<b>
<set>erase</set>
<set><a/>erase</set>
<d>
<set>erase</set>
</d>
</b>
<c>
<x>
</x>
</c>
<e>
<y>
<set>erase</set>
<q>
</q>
</y>
<z>
<p>
<set>erase</set>
</p>
</z>
</e>
</a>
选择所需元素的一个表达式是:
基于XSLT的验证:
请注意,以下两个表达式非常不正确:
*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]
或:
这两个表达式存在不止一个问题:
它们是相对表达式,无论应用于哪个初始上下文,它们都无法选择层次结构中所有需要的元素,且深度和结构未定义
set[text='erase']不仅选择表单的元素:
<set>
xyz
<a/>erase</set>
<set>
xyz
<a/>erase</set>
选择表单的元素:
<set>
xyz
<a/>erase</set>
<set>
xyz
<a/>erase</set>
这是我的第二次尝试:
//*[ set[count(node())=1 and text()='erase'] and
not( ancestor::*[ set[count(node())=1 and text()='erase']])
]
此选择通过了我的第一个答案中显示的测试用例。只有此选项没有选择任何内容。第二个子句说,只给具有不包含文本擦除的set子级的祖先的节点。在本文档中,所有set元素都是do.Hmm。。这没有选择所需的元素。我认为这不起作用的原因是您已设置!=在节点上,文本值为“擦除”,而不是在节点上。为了将@harpo的解决方案用文字表达出来,他首先选择了所有具有擦除功能的节点,然后从结果中添加了一个额外的条件来移除所有没有带有擦除功能的节点。XSLT是一种多么有趣的语言啊!有两个人总是有正确的答案:诺瓦切夫和凯。今天我在一天之内被他们两个纠正了。我想这是我自我提升的幸运日:---@SeanB.Durkin:如果你买了一本迈克尔·凯写的拼写正确的书,你会非常幸运。请在此处查看这些书的链接:@SeanB.Durkin:谢谢您的精彩报道。我及时更新了答案,现在您提供的XML文档不再是反例了…:因此,请您更新您问题中现在错误的陈述:啊。。非常感谢您的逻辑。@user1207560,根据Dimitre的回答,我已经修改了它,以便通过添加到front//的单个表达式选择所有所需的节点。user1207560:您接受了错误的答案-只需在代码中使用建议的表达式来验证它没有选择所需的元素。我的回答解释了为什么会这样。这可能是一个陈腐的问题,但我对诺瓦切夫的回答有疑问。如果将以下文档应用于Novatchev的基于XSLT的自检程序验证,那么至少就我理解提问者的要求而言,会产生错误的输出:我不能将反例放在注释中,因为它太大了,所以我把它附在了我的答案上。@SeanB.Durkin:谢谢你提供了一个很好的示例XML文档。我已经用一个XPath表达式编辑了我的答案,它选择了正确的和预期的节点集。。。是否可以将[.='erase'和notnode[2]]简化为['erase'和notnode[2]]?您似乎更喜欢使用索引谓词测试序列长度,而不是使用计数函数?这种偏好仅仅是风格的问题吗?还是谓词方法在清晰度、性能等方面有真正的好处?@SeanB.Durkin:No,在['erase'和notnode[2]]中,and运算符的第一个参数是一个非空字符串,它被转换为true-与的结果截然不同。='删除'。至于测试一个节点集中没有第二个节点,这比使用计数要有效得多——想象一下,必须计数1000个节点才能看到这个数字大于1。@Dimitre:这只是一个小问题。如果我想选择元素而不是它们的父元素//。。。。我该怎么做?我尝试过//设置[包含],“擦除”]将选择全部。。但是如何忽视后代呢?
<a>
<b>
<set>erase</set>
<set>
<a/>erase
</set>
<d>
<set>erase</set>
</d>
</b>
<c>
<x> </x>
</c>
<e>
<y>
<set>erase</set>
<q> </q>
</y>
<z>
<p>
<set>erase</set>
</p>
</z>
</e>
</a>
b
y
p
*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]
*[set[text()='erase']][ancestor::*[set[text()!='erase']]]
<set>erase</set>
<set>
xyz
<a/>erase</set>
set[text()!='erase']
<set>
xyz
<a/>erase</set>
//*[ set[count(node())=1 and text()='erase'] and
not( ancestor::*[ set[count(node())=1 and text()='erase']])
]