xslt - xpath获取祖先节点的位置

  显示原文与译文双语对照的内容

我有如下所示的XML结构:


<inventory>
 <location>
 <category>
 <children>
 <book>
 <title>Harry Potter</title>
 <price>$28.50</price>
 </book>
 <cd>
 <title>Frozen</title>
 <price>12.8</price>
 </cd>
 </children>
 </category>
 <category>
 <adult>
 <book>
 <title>Da vinci code</title>
 <price>32.50</price>
 </book>
 <cd>
 <title>Da vinci code</title>
 <price>13.80</price>
 </cd>
 </adult>
 </category>
 </location>
 <location>
 <category>
 <cooking>
 <book>
 <title>everyday Italian</title>
 <price>30.50</price>
 </book>
 </cooking>
 </category>
 </location>
</inventory>

我想打印的内容是:

Location category# category title price
1 1 children Harry 28.50
2 1 cooking everyday... 30.50
1 2 cd Da vinci code 13.8

如果我当前在每个 <title> 元素上,如何获得 <location><category>的位置?

我尝试过的是:


count(ancestor::location/preceding-silbing::location) + 1
count(ancestor::category/preceding-silbing::category) + 1

但是他们中的任何一个。

时间: 作者:

因为你使用的是 XSLT 2.0,所以尝试使用更强大的 xsl:number 插件,而不是使用。

位置:


<xsl:number select="ancestor::location"/>

类别:


<xsl:number select="ancestor::category"/>


下面是一个更详细的例子。 ( 注意,这只是为了说明;它可能不是最有效的例子。)

XML输入


<inventory>
 <location>
 <category>
 <children>
 <book>
 <title>Harry Potter</title>
 <price>$28.50</price>
 </book>
 <cd>
 <title>Frozen</title>
 <price>12.8</price>
 </cd>
 </children>
 </category>
 <category>
 <adult>
 <book>
 <title>Da vinci code</title>
 <price>32.50</price>
 </book>
 <cd>
 <title>Da vinci code</title>
 <price>13.80</price>
 </cd>
 </adult>
 </category>
 </location>
 <location>
 <category>
 <cooking>
 <book>
 <title>everyday Italian</title>
 <price>30.50</price>
 </book>
 </cooking>
 </category>
 </location>
</inventory>

2.0


<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:local="local">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="column-widths">
 <cols>
 <col name="location" width="10"/>
 <col name="categorynbr" width="11"/>
 <col name="category" width="{max((string-length('category'),//category/*/string-length(name())))+2}"/>
 <col name="title" width="{max((string-length('title'),//category/*/book/title/string-length(normalize-space())))+2}"/>
 <col name="price" width="{max((string-length('price'),//category/*/book/price/string-length(normalize-space())))+2}"/>
 </cols>
 </xsl:variable>

 <xsl:function name="local:padValue">
 <xsl:param name="colname"/>
 <xsl:param name="value"/>
 <xsl:variable name="padding">
 <xsl:for-each select="1 to xs:integer($column-widths/*/col[@name=$colname]/@width) - string-length($value)">
 <xsl:text> </xsl:text>
 </xsl:for-each> 
 </xsl:variable>
 <xsl:value-of select="concat($value,$padding)"/>
 </xsl:function>

 <xsl:template match="/*">
 <xsl:value-of select="concat(local:padValue('location','Location'),
 local:padValue('categorynbr','category#'),
 local:padValue('category','category'),
 local:padValue('title','title'),
 local:padValue('price','price'),'&#xA;')"/>
 <xsl:apply-templates select="*/*/*/book">
 <xsl:sort>
 <xsl:number select="ancestor::category"/>
 </xsl:sort>
 </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="book">
 <xsl:variable name="loc">
 <xsl:number select="ancestor::location"/> 
 </xsl:variable>
 <xsl:variable name="cat">
 <xsl:number select="ancestor::category"/> 
 </xsl:variable>
 <xsl:value-of select="concat(local:padValue('location',$loc),
 local:padValue('categorynbr',$cat),
 local:padValue('category',../local-name()),
 local:padValue('title',normalize-space(title)),
 local:padValue('price',normalize-space(price)),'&#xA;')"/>
 </xsl:template>

</xsl:stylesheet>

输出


Location category# category title price 
1 1 children Harry Potter $28.50 
2 1 cooking everyday Italian 30.50 
1 2 adult Da vinci code 32.50 

作者:

我的假设是,这就是你要做的:

你的上下文节点是输入文档中的title 元素之一。 现在你想知道

  • 上下文节点所在的location 元素的( 基于一个) 索引,在它的父 inventory 元素中

  • 上下文节点所在的category 元素的( 基于一个) 索引,在它的父 category 元素中

对于提供的XML输入,可以使用XPath表达式来实现


count(ancestor::location/preceding-sibling::location) + 1


count(ancestor::category/preceding-sibling::category) + 1

确保轴和节点测试由两个冒号( 通过编辑更正) 分隔。 同时确保 preceding-sibling 拼写正确。

在位置步骤 ancestor::locationancestor::category 之后不能添加谓词 [1],明确地指出你在反向文档顺序( 例如,最接近的祖先) 之后的第一个祖先。 如果XML包含嵌套的location 或者 category 元素,则这将是必要的。

...