XPath 1.0在XML树中具有属性的最接近的前一个和/或祖先节点
下面是三个XML树 (一)XPath 1.0在XML树中具有属性的最接近的前一个和/或祖先节点,xml,xslt,xpath,Xml,Xslt,Xpath,下面是三个XML树 (一) (二) 在这两种情况下,理想的结果都是id5 使用XSLT1.0和XPath1.0,我可以从(1)中获取祖先 或(2)中的前一个节点 如何使用书签中的id获取最近的祖先或前面的节点? 我需要一个xsl:value,它匹配两种情况。谢谢 编辑: 解决方案还应涵盖此结构。所需id仍然为5 (三) 试试: <xsl:value-of select="//bookmark/ancestor::*[1]/descendant-or-self::
(二)
在这两种情况下,理想的结果都是id5
使用XSLT1.0和XPath1.0,我可以从(1)中获取祖先
或(2)中的前一个节点
如何使用书签中的id获取最近的祖先或前面的节点?我需要一个xsl:value,它匹配两种情况。谢谢 编辑: 解决方案还应涵盖此结构。所需id仍然为5 (三)
试试:
<xsl:value-of
select="//bookmark/ancestor::*[1]/descendant-or-self::*[last()-1]/@id"/>
另一个普遍解决办法:
<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>
使用:
(//bookmark/ancestor::*[@id][1]/@id
|
//bookmark/preceding::*[@id][1]/@id
)
[last()]
验证:使用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>
当应用于提供的三个XML文档中的任何一个时,会生成所需的正确结果:
(//bookmark/ancestor::*[@id][1]/@id
|
//bookmark/preceding::*[@id][1]/@id
)
[last()]
5
我强烈建议使用用于玩/学习XPath的您的解决方案在特殊情况下有效。但如果我在两个XML上的书签后添加更多id为的节,您的解决方案将给出错误的结果。将编辑我的示例,使其在书签后有一些部分。@therealmarv:对。我假设了具体的结构。检查我的第二个解决方案。@Therelmarv:corrected
last()
→ 1
在lastSibling
变量中。您的解决方案是一个很好的方法。它给了我一些想法。但这不是一个普遍的解决办法。我再次编辑了我的示例。最近的祖先可能不是父节点,id可能位于前一个节点的子节点的某个位置。哇。您更通用的解决方案适用于(1)和(3)。非常感谢!:-)但是,它不适用于(2),解决方案为空。还在弄清楚原因是什么。希望我能解决显示所有xpath轴的itPicture:好问题,+1。请参阅我的答案,了解一行XPath表达式,该表达式在所有三种情况下都精确地选择所需的属性节点。:)
<xsl:value-of
select="//bookmark/ancestor::*[1]/descendant-or-self::*[last()-1]/@id"/>
<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>
<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>
(//bookmark/ancestor::*[@id][1]/@id
|
//bookmark/preceding::*[@id][1]/@id
)
[last()]
<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>