XSLT中除第一个元素之外的元素分组

时间:2015-05-21 12:12:02

标签: xml xslt grouping sequence

(这个问题的标题可能不正确,所以如果有人有更好的建议我会改变它。)

我有一个体育赛事的结果列表,我希望得到以下输出:

<p>
1) John Doe, Norway 1.23,45, 2) Dave Doe, Norway 0.15 behind, 3) Nicholas Doe, Norway Same Time, 4) Barack Doe, USA S.T, 5) Vladimir Doe, Russia 1.00,00 behind, 6) Xi Min Doe, China S.T. .... 
</p>

用文字说: 第一个结果有总时间。第二个结果使用间隙,我们添加后面,如果第三个结果与第二个结果具有相同的间隙,我们给出同一时间。如果第四个结果与第二个结果具有相同的差距,我们将其缩短为s.t. 如果存在新的差距,我们会写出差距,但是与该组中第一个差距相同的所有结果都只有s.t。

替代产品:

<results>
<result>
<rank>1</rank>
<name>John</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:23:45</time>
<gap>00:00</gap>
</result>

<result>
<rank>2</rank>
<name>Dave</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:00</time>
<gap>00:15</gap>
</result>

<result>
<rank>3</rank>
<name>Nicholas</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:00</time>
<gap>same time</gap>
</result>

<result>
<rank>4</rank>
<name>Barack</name>
<lastname>Doe</name>
<country>USA</country>
<time>1:24:00</time>
<gap>s.t.</gap>
</result>

<result>
<rank>5</rank>
<name>Vladimir</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:45</time>
<gap>01:15</gap>
</result>

<result>
<rank>6</rank>
<name>Xi Min</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:45</time>
<gap>s.t.</gap>
</result>
</results>

XML与此非常相似:

<results>
<result>
<rank>1</rank>
<name>John</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:23:45</time>
<gap>00:00</gap>
</result>

<result>
<rank>2</rank>
<name>Dave</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:00</time>
<gap>00:15</gap>
</result>

<result>
<rank>3</rank>
<name>Nicholas</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:00</time>
<gap>00:15</gap>
</result>

<result>
<rank>4</rank>
<name>Barack</name>
<lastname>Doe</name>
<country>USA</country>
<time>1:24:00</time>
<gap>00:15</gap>
</result>

<result>
<rank>5</rank>
<name>Vladimir</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:45</time>
<gap>01:15</gap>
</result>

<result>
<rank>6</rank>
<name>Xi Min</name>
<lastname>Doe</name>
<country>Norway</country>
<time>1:24:45</time>
<gap>01:15</gap>
</result>
</results>

输出,代码如下: 我正在使用XSLT 2.0,但是可能有人在使用1.0,所以任何支持(或者制作所有)XSLT版本的建议,我和很多人在同样的情况下都会非常高兴。

2 个答案:

答案 0 :(得分:0)

以下样式表:

XSLT 2.0

$brand::where('year','>',2010)->take(20)->get()?

应用于您的示例输入(在更正不匹配的<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="*"/> <!-- identity transform --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="/results"> <xsl:copy> <xsl:for-each-group select="result" group-by="gap"> <xsl:apply-templates select="current-group()"/> </xsl:for-each-group> </xsl:copy> </xsl:template> <xsl:template match="result"> <xsl:copy> <xsl:apply-templates select="* except gap"/> <gap> <xsl:value-of select="if (position()=1) then gap else 'SAME TIME'" /> </gap> </xsl:copy> </xsl:template> </xsl:stylesheet> name标记之后!),将返回:

lastname

答案 1 :(得分:0)

这是我解决问题的方法。在帖子之后我被告知只有前10名应该被渲染,所以我在代码周围添加了一个if rank&lt; = 10。

此处的原始数据源结构的某些部分(仅显示数据,名称和ID已被删除)。

如果您发现奇怪的内容,请随时发表评论或提问。

<RESULT>
        <rank>42</rank>
        <bib>43</bib>
        <name>John</name>
        <surname>Doe</surname>
        <short_team>ABA</short_team>
        <long_team>ABBA</long_team>
        <time>04:42:18</time>
        <gap>13</gap>
        <code>ABA1234</code>
        <nationality>BEL</nationality>
    </RESULT>

要分组并获得正确输出的XSLT部分。请注意,这是生产代码,因此某些文本可能与示例不同。我在有差异的地方添加了评论:

<xsl:for-each-group select="RESULT" group-by="time">
            <xsl:for-each select="current-group()">
                <xsl:if test="rank &lt;= 10">
                    <xsl:value-of select="rank"/>
                    <xsl:text>) </xsl:text>
                    <xsl:value-of select="name"/>
                    <xsl:text> </xsl:text>
                    <xsl:variable name="surname">
                        <xsl:for-each select="tokenize(surname, ' ')">
                            <xsl:value-of
                                select="concat(upper-case(substring(., 1, 1)), lower-case(substring(., 2)))"/>
                            <xsl:text> </xsl:text>
                        </xsl:for-each>
                    </xsl:variable>
                    <xsl:value-of select="normalize-space($surname)"/>

                    <xsl:text>, </xsl:text>
                    <xsl:value-of select="nationality"/>
                    <xsl:text> (</xsl:text>
                    <xsl:value-of select="long_team"/>
                    <xsl:text>)</xsl:text>
                    <xsl:text> </xsl:text>
                    <xsl:choose>
                        <xsl:when test="rank = '1'">
                            <!-- the replace is just there to get the time in the correct format -->
                            <xsl:value-of select="replace(time, ':', '.')"/>
                        </xsl:when>
                        <xsl:when test="rank = '2'">
                            <xsl:choose>
                                <xsl:when test="gap != ''">
                                    <xsl:if test="string-length(gap) = 2">
                                       <!-- this text is here because the gap might just have two characters, and we want it like this 0.12 -->
                                        <xsl:text>0.</xsl:text>
                                    </xsl:if>
                                    <xsl:value-of select="replace(gap, ':', '.')"/>
                                    <!-- This is norwegian text for minutes behind (shortened) -->
                                    <xsl:text> min. bak</xsl:text>
                                </xsl:when>
                                <xsl:otherwise>
                                    <!-- This is norwegian for same time -->
                                    <xsl:text> samme tid</xsl:text>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:choose>
                                <xsl:when test="position() = 1">
                                    <xsl:if test="string-length(gap) = 2">
                                        <xsl:text>0.</xsl:text>
                                    </xsl:if>
                                    <xsl:value-of select="replace(gap, ':', '.')"/>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:text> s.t.</xsl:text>
                                </xsl:otherwise>
                            </xsl:choose>

                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:choose>
                        <xsl:when test="position() != last()">
                            <xsl:text>, </xsl:text>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:text>, </xsl:text>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each-group>