首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSL分组输出

XSL分组输出
EN

Stack Overflow用户
提问于 2012-07-13 18:52:09
回答 2查看 178关注 0票数 2

我有一个包含记录的XML,一些记录相互关联,因此,我希望在输出中将它们组合在一起。

XML:

代码语言:javascript
复制
<Records>
   <Record id="1" group="10" />
   <Record id="2" group="20" />
   <Record id="3" group="20" />
   <Record id="4" group="20" />
</Records>

当前,我显示

代码语言:javascript
复制
<span>1</span><span>2</span><span>3</span><span>4</span>

我想要显示的是(基于具有相同组的记录)

代码语言:javascript
复制
<span>1</span><span>2-4</span>

我已经研究过使用preceding-sibling::Record/@group来查看分组是否在Record的迭代之间发生了变化,但我正在努力弄清楚如何实现我所需要的2-4分组。

以下是我到目前为止所做的,并穿插了一些评论来说明我正在尝试做的事情:

代码语言:javascript
复制
<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>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-13 20:33:24

此转换

代码语言:javascript
复制
<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文档上应用时的

代码语言:javascript
复制
<Records>
    <Record id="1" group="10" />
    <Record id="2" group="20" />
    <Record id="3" group="20" />
    <Record id="4" group="20" />
</Records>

生成所需的、正确的结果

代码语言:javascript
复制
<span>1</span><span>2-4</span>

说明

  1. 这是位置分组,使用一个键来定义组成一个组的所有相邻记录元素。
  2. 这是一种有效的(次线性)算法,因为使用了键。使用兄弟轴的算法在时间复杂度上通常是O(N^2) --二次型,如果兄弟轴的总数N很大,那么算法可能会太慢。
票数 3
EN

Stack Overflow用户

发布于 2012-07-13 19:10:48

如果你的节点总是连续的,你可以使用一些简单的东西,比如

代码语言:javascript
复制
<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>

但如果不是这样,您可能需要一个递归函数来获得更健壮的结果,并手动计算节点数

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11469043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档