2012-07-13 58 views
2

我有一个XML与记录,一些记录相互关联,因此,我想在输出中将它们组合在一起。XSL分组输出

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来查看分组是否在迭代之间改变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

你使用XSLT 2.0处理器等撒克逊9或AltovaXML,这样就可以利用的xsl':换每个组选择=“录制”组相邻=“@基”>'? – 2012-07-13 10:54:35

+0

不幸的是,它只是XSLT 1 - 我用它来浏览器渲染 – Chris 2012-07-13 10:56:54

+0

看看你是否可以自己调整http://stackoverflow.com/questions/11451989/xsl-count-continuous-nodes/11456109#11456109你的需求,如果不是说我相信后来有人能帮上忙。 – 2012-07-13 11:04:15

回答

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> 

说明

  1. 这是使用密钥来定义包括一组所有相邻记录元件位置分组

  2. 这是一个有效的(次线性)算法,因为使用了密钥。使用同级轴的算法通常为O(N^2) - 时间复杂度为二次方,如果兄弟姐妹总数大,则速度可能太慢。

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> 

,但如果没有你可能需要一个递归函数来拿出一些更强大的和人工计数节点