给出以下XML文档:
<doc>
<foo>
<key1>1</key1>
<key2>1</key2>
</foo>
<foo>
<key1>1</key1>
<key2>1</key2>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
</foo>
</doc>
我需要将(key1,key2)键入的每组foo元素添加到组中的位置编号,如下所示:
<doc>
<foo>
<key1>1</key1>
<key2>1</key2>
<pos>1</pos>
</foo>
<foo>
<key1>1</key1>
<key2>1</key2>
<pos>2</pos>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
<pos>1</pos>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
<pos>2</pos>
</foo>
<foo>
<key1>1</key1>
<key2>2</key2>
<pos>3</pos>
</foo>
</doc>
我尝试创建一个密钥<xsl:key match="foo" use="concat(key1, '|', key2)" name="group"/>
,我应该允许按其键值对foo
元素进行分组,但我对如何编写相应的模板感到茫然创建pos
元素。
模板可能看起来像这样:
<xsl:template match="foo[???]">
<xsl:copy-of select="."/>
<xsl:element name="pos">
<xsl:value-of select="position()" />
</xsl:element>
</xsl:template>
但是要为&#39; ???&#39;?
提供什么答案 0 :(得分:4)
您可以使用
Some-Other-Template.cshtml
完整的样式表
<xsl:template match="foo">
<xsl:variable name="this" select="."/>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<pos>
<xsl:for-each select="key('group', concat(key1, '|', key2))">
<xsl:if test="generate-id() = generate-id($this)">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>
</pos>
</xsl:copy>
</xsl:template>
使用XSLT 2.0(以及functx
function library的帮助)代码更紧凑:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key match="foo" use="concat(key1, '|', key2)" name="group"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo">
<xsl:variable name="this" select="."/>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<pos>
<xsl:for-each select="key('group', concat(key1, '|', key2))">
<xsl:if test="generate-id() = generate-id($this)">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>
</pos>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
您也可以尝试使用此Muenchian分组版本:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="k1k2" match="foo" use="concat(key1, '|', key2)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/doc">
<xsl:copy>
<xsl:for-each
select="foo[generate-id() = generate-id(key('k1k2', concat(key1, '|', key2))[1])]" >
<!-- group -->
<xsl:for-each
select="key('k1k2', concat(key1, '|', key2))" >
<!-- group member-->
<xsl:apply-templates select="." >
<xsl:with-param name="group-pos" select="position()" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="foo">
<xsl:param name="group-pos" />
<xsl:copy>
<xsl:apply-templates select="*" />
<pos>
<xsl:value-of select="$group-pos"/>
</pos>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>