如何将没有属性的XML分组

时间:2018-08-02 10:46:50

标签: xml xslt transformation

我的任务是修改前一段时间离开公司的其他人制造的工具。最后要做的是按日期对XML进行分组。我发现的每个示例都可以使用带有属性的XML,因此它并不是真的有用。

我的XML没有单一属性,其结构如下:

<report>
<clientInfo>
...
</clientInfo>
<bills>
    <bill>
        <section>
            <dateSegment>20-07-1990</dateSegment>
            <money>100</money>
            <days>9</days>
        </section>
        <section>
            <dateSegment>20-08-1990</dateSegment>
            <money>130</money>
            <days>4</days>
        </section>
        <section>
            <dateSegment>20-09-1990</dateSegment>
            <money>110</money>
            <days>5</days>
        </section>
    </bill>
    <bill>
        <section>
            <dateSegment>20-07-1990</dateSegment>
            <money>230</money>
            <days>11</days>
        </section>
        <section>
            <dateSegment>20-10-1990</dateSegment>
            <money>210</money>
            <days>3</days>
        </section>
    </bill>
    ...
</bills>
...
</report>

我必须按相同的日期分组,并每组进行总结。我曾尝试根据how to apply group by on xslt elements的帖子编写模板,但这远没有达到预期的效果。

<xsl:key name="by_date" match="section" use="@dateSegment" />

<xsl:template name="test">
    <xsl:element name="AllSections">
        <xsl:for-each-group select="*" group-by="@dateSegment">
            <xsl:element name="dateSegment">
                <xsl:attribute name="value">
                    <xsl:value-of select="@dateSegment" />
                </xsl:attribute>
                <xsl:for-each select="current-group()">
                    <xsl:element name="section">
                        <xsl:element name="money"><xsl:value-of select="@money" /></xsl:element>
                        <xsl:element name="days"><xsl:value-of select="@days" /></xsl:element>
                    </xsl:element>
                </xsl:for-each>
              </xsl:element>
       </xsl:for-each-group>
    </xsl:element>
</xsl:template>

尝试用<xsl:call-template name="test"/>调用它,但是没有任何反应,结果为空。

预期输出:

任一

<dateSegment value="20-07-1990">
    <section>
        <money>100</money>
        <days>9</days>
    </section>
    <section>
        <money>230</money>
        <days>11</days>
    </section>
</dateSegment>
<dateSegment value="20-08-1990">
    <section>
        <money>130</money>
        <days>4</days>
    </section>
</dateSegment>
...

<dateSegment>
    <money>340</money>
    <days>11</days> (max value from <days> in same section)
</dateSegment>
<dateSegment>   
    <money>130</money>
    <days>4</days>
    </section>
</dateSegment>

将XML分配给变量会很有帮助,这样我就可以做些事情。

阿尔迪(Alrdy)问我每个人都可以,但我们每个人都不从事这种工作,没有人能够帮助我。

任何想法怎么做?

1 个答案:

答案 0 :(得分:1)

首先,您提到没有属性,但是XSLT仍在使用属性语法。即@dateSegment。引用元素应为dateSegment

似乎您也希望对section个元素进行分组,而不管它们位于哪个bill元素中(而不是在每个bill元素中进行单独分组)。但是您当前的XSLT正在执行<xsl:for-each-group select="*",这实际上只会在您使用bill元素时为您提供结果。确实,您希望放置在bills元素上,并执行以下操作:

<xsl:for-each-group select="bill/section" group-by="dateSegment">

尝试使用此XSLT(已简化为删除xsl:elementxsl:attribute的使用)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output method="xml" indent="yes" />

<xsl:template match="bills">
    <AllSections>
        <xsl:for-each-group select="bill/section" group-by="dateSegment">
            <dateSegment value="{dateSegment}">
                <xsl:for-each select="current-group()">
                    <section>
                        <money><xsl:value-of select="money" /></money>
                        <days><xsl:value-of select="days" /></days>
                    </section>
                </xsl:for-each>
            </dateSegment>
        </xsl:for-each-group>
    </AllSections>
</xsl:template>

</xsl:stylesheet>

如果您想汇总结果,请执行此操作

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output method="xml" indent="yes" />

<xsl:template match="bills">
    <AllSections>
        <xsl:for-each-group select="bill/section" group-by="dateSegment">
            <dateSegment value="{dateSegment}">
                <money><xsl:value-of select="sum(current-group()/money)" /></money>
                <days><xsl:value-of select="max(current-group()/days)" /></days>
            </dateSegment>
        </xsl:for-each-group>
    </AllSections>
</xsl:template>

</xsl:stylesheet>