我有一个类似以下的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
但它们都不起作用。
答案 0 :(得分:1)
由于您使用的是XSLT 2.0,请尝试使用功能更强大的xsl:number
代替count()
。
位置:
<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>
XSLT 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'),'
')"/>
<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)),'
')"/>
</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
答案 1 :(得分:0)
我的假设是,这就是你所追求的:
您的上下文节点是输入文档中的title
元素之一。现在你想知道
您的上下文节点包含在其父location
元素中的inventory
元素的(从一开处)索引
您的上下文节点包含在其父category
元素中的category
元素的(从一开处)索引
对于提供的XML输入,可以使用XPath表达式
实现count(ancestor::location/preceding-sibling::location) + 1
和
count(ancestor::category/preceding-sibling::category) + 1
确保轴和节点测试由两个冒号分隔(通过编辑校正)。另外,请确保preceding-sibling
拼写正确。
您可以在位置步骤[1]
和ancestor::location
之后添加谓词ancestor::category
,以明确说明您在第一个祖先倒退后文件顺序(即最近的祖先)。如果XML包含嵌套的location
或category
元素,那么必需。