XPath 1.0 在 XML 树中具有属性的最接近的前一个和/或祖先节点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6554067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XPath 1.0 closest preceding and/or ancestor node with an attribute in a XML Tree
提问by therealmarv
Here are three XML-trees
这是三个 XML 树
(1)
(1)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1">
<section id="2"/>
<section id="3"/>
<section id="9"/>
</section>
<section id="4">
<section id="5">
<section>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</section>
</section>
</content>
(2)
(2)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1"/>
<section id="2">
<section id="9">
<section id="10">
<section id="11"/>
</section>
</section>
<section>
<section id="4">
<section id="5"/>
</section>
</section>
<section/>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</content>
The desired result is in both cases the id 5.
在这两种情况下,所需的结果都是 id 5。
With XSLT 1.0 and XPath 1.0 I can either get the ancestor from (1)
使用 XSLT 1.0 和 XPath 1.0,我可以从 (1) 中获取祖先
<xsl:value-of select="//bookmark/ancestor::*[@id][1]/@id"/>
or the preceding node from (2)
或 (2) 中的前一个节点
<xsl:value-of select="//bookmark/preceding::*[@id][1]/@id"/>
How do I get the nearestancestor orpreceding node with an id from my bookmark?
I need a single xsl:value-of which matches both cases. Thanks.
如何从我的书签中获取最近的祖先节点或具有 id 的前一个节点?
我需要一个 xsl:value-of 匹配这两种情况。谢谢。
EDIT:
编辑:
The solution should also cover this structure. Desired id is still 5.
解决方案还应涵盖此结构。所需的 id 仍然是5。
(3)
(3)
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section id="1">
<section id="2"/>
<section id="3"/>
<section id="9"/>
</section>
<section id="4">
<section>
<section id="10"/>
<section id="5"/>
<section>
<bookmark/> <!-- here's the bookmark-->
<section id="6">
<section id="7">
<section id="8"/>
</section>
</section>
</section>
</section>
</section>
</content>
回答by Dimitre Novatchev
Use:
使用:
(//bookmark/ancestor::*[@id][1]/@id
|
//bookmark/preceding::*[@id][1]/@id
)
[last()]
Verification: Using XSLT as host of XPath, the following transformation:
验证:使用XSLT作为XPath的宿主,如下转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select=
"(//bookmark/ancestor::*[@id][1]/@id
|
//bookmark/preceding::*[@id][1]/@id
)
[last()]"/>
</xsl:template>
</xsl:stylesheet>
when applied on any of the provided three XML documents, produces the wanted, correct result:
当应用于提供的三个 XML 文档中的任何一个时,会产生所需的正确结果:
5
5
I strongly recomment using the XPath Visualizerfor playing with / learning XPath.
我强烈建议使用XPath Visualizer来玩/学习 XPath。
回答by Grzegorz Szpetkowski
Try with :
尝试:
<xsl:value-of
select="//bookmark/ancestor::*[1]/descendant-or-self::*[last()-1]/@id"/>
It returns 5for both XML documents.
它返回5两个 XML 文档。
EDIT:
编辑:
In such conditions you could use simple xsl:choose:
在这种情况下,您可以使用 simple xsl:choose:
<xsl:variable name="lastSibling"
select="//bookmark/preceding-sibling::*[1]"/>
<xsl:choose>
<xsl:when test="$lastSibling">
<xsl:value-of
select="$lastSibling/descendant-or-self::*[last()]/@id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//bookmark/ancestor::*[@id][1]/@id"/>
</xsl:otherwise>
</xsl:choose>
Another general solution:
另一个通用解决方案:
<xsl:for-each
select="//section[following::bookmark or descendant::bookmark][@id]">
<xsl:if test="position() = last()">
<xsl:value-of select="./@id"/>
</xsl:if>
</xsl:for-each>

