我有一个包含记录的XML,一些记录彼此关联,因此,我想在输出中将它们组合在一起。
XML:
<Records>
<Record id="1" group="10" />
<Record id="2" group="20" />
<Record id="3" group="20" />
<Record id="4" group="20" />
</Records>
目前,我显示
<span>1</span><span>2</span><span>3</span><span>4</span>
我想要显示的是(基于具有相同组的记录)
<span>1</span><span>2-4</span>
我已经考虑过使用preceding-sibling::Record/@group
查看分组是否在Record
s的迭代之间发生了变化,但我正在努力弄清楚如何实现我需要的2-4
分组。
这是我到目前为止的内容,其中穿插了一些评论来说明我想要做的事情:
<xsl:for-each select="Records/Record">
<xsl:if test="@group != preceding-sibling::Record/@group">
<!-- obviously here we need 2-4...somehow? -->
<span><xsl:value-of="@id" /></span>
</xsl:if>
</xsl:for-each>
答案 0 :(得分:3)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="Record"
use="generate-id(preceding-sibling::*
[not(@group = current()/@group)
][1])"/>
<xsl:template match="/*">
<xsl:apply-templates mode="makeGroup" select=
"Record[not(@group = preceding-sibling::*[1]/@group)]"/>
</xsl:template>
<xsl:template match="Record" mode="makeGroup">
<xsl:variable name="vGroup"
select="key('kFollowing', generate-id(preceding-sibling::*[1]))"/>
<span>
<xsl:value-of select="$vGroup[1]/@id"/>
<xsl:if test="$vGroup[2]">
<xsl:value-of select="concat('-', $vGroup[last()]/@id)"/>
</xsl:if>
</span>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<Records>
<Record id="1" group="10" />
<Record id="2" group="20" />
<Record id="3" group="20" />
<Record id="4" group="20" />
</Records>
生成想要的正确结果:
<span>1</span><span>2-4</span>
<强>解释强>:
这是位置分组,使用键定义构成组的所有相邻记录元素。
这是一个高效(次线性)算法,因为使用了密钥。使用兄弟轴的算法通常为O(N^2)
- 时间复杂度为二次方,如果兄弟姐妹N
的总数很大,则可能太慢。
答案 1 :(得分:1)
如果你的节点总是连续的,你可以使用像
这样简单的东西<xsl:template match="/">
<xsl:for-each select="Records/Record">
<xsl:if test="position() = 1 or @group != preceding-sibling::Record[1]/@group">
<span><xsl:value-of select="@id" />
<xsl:if test="following-sibling::Record/@group = @group">
<xsl:variable name="following" select="following-sibling::Record[@group = ./@group]"/>
- <xsl:value-of select="$following[count($following)]/@id"/>
</xsl:if>
</span>
</xsl:if>
</xsl:for-each>
</xsl:template>
但如果没有,你可能需要一个递归函数来提出更强大的东西并手动计算节点