在XSLT中对直接节点进行分组

时间:2014-12-10 11:03:04

标签: xslt

我正在使用XSLT 1.0版本,我有以下XML进行转换,

<Root>
	<Child No="1" Month="0" Date="13/08/2014" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="2" Month="1" Date="13/09/2014" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="3" Month="2" Date="13/10/2014" Payment="200">
		<Totals amount="200"/>
	</Child>
	<Child No="4" Month="3" Date="13/11/2014" Payment="300">
		<Totals amount="300"/>
	</Child>
	<Child No="5" Month="4" Date="13/12/2014" Payment="300">
		<Totals amount="300"/>
	</Child>
	<Child No="6" Month="5" Date="13/01/2015" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="7" Month="6" Date="13/01/2015" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="8" Month="7" Date="13/01/2015" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="9" Month="8" Date="13/01/2015" Payment="100">
		<Totals amount="100"/>
	</Child>
	<Child No="10" Month="9" Date="13/01/2015" Payment="100">
		<Totals amount="100"/>
	</Child>
</Root>

我想将XML转换为

<PPS>
	<PP>
		<Ps>
			<StartMonth>0</StartMonth>
			<EndMonth>1</EndMonth>
			<P>
				<Amount>100</Amount>
				<startP>1</startP>
			</P>
			<P>
				<Amount>100</Amount>
				<startP>2</startP>
			</P>
		</Ps>
	</PP>
	<PP>
		<Ps>
			<StartMonth>2</StartMonth>
			<EndMonth>2</EndMonth>
			<P>
				<Amount>200</Amount>
				<startP>3</startP>
			</P>
		</Ps>
	</PP>
	<PP>
		<Ps>
			<StartMonth>3</StartMonth>
			<EndMonth>4</EndMonth>
			<P>
				<Amount>300</Amount>
				<startP>4</startP>
			</P>
			<P>
				<Amount>300</Amount>
				<startP>5</startP>
			</P>
		</Ps>
	</PP>
	<PP>
		<Ps>
			<StartMonth>5</StartMonth>
			<EndMonth>9</EndMonth>
			<P>
				<Amount>100</Amount>
				<startP>6</startP>
			</P>
			<P>
				<Amount>100</Amount>
				<startP>7</startP>
			</P>
			<P>
				<Amount>100</Amount>
				<startP>8</startP>
			</P>
			<P>
				<Amount>100</Amount>
				<startP>9</startP>
			</P>
			<P>
				<Amount>100</Amount>
				<startP>10</startP>
			</P>
		</Ps>
	</PP>
</PPS>
每次我想创建一个与上次付款不同的“P”。 这是伪代码,当child [n] / Payment&lt;&gt;时创建一个新的PP子[N-1] /支付。 P.S.,即使它有一些值,我也不想考虑Totals节点。

非常感谢提前。

1 个答案:

答案 0 :(得分:0)

您可以使用以下XSLT。如果是在XSLT2.0中,它就不会那么久了:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Root">
    <PPS>
        <xsl:for-each select="Child">
            <xsl:variable name="Payment" select="@Payment"/>
            <xsl:variable name="start-end">
                <StartMonth>
                    <xsl:value-of select="@Month"/>
                </StartMonth>
                <xsl:choose>
                    <xsl:when test="following-sibling::*[1][self::Child and @Payment = $Payment]">
                        <EndMonth>
                            <xsl:apply-templates select="following-sibling::*[1]" mode="month">
                                <xsl:with-param name="Payment" select="$Payment"/>
                            </xsl:apply-templates>
                        </EndMonth>
                    </xsl:when>
                    <xsl:otherwise>
                        <EndMonth>
                            <xsl:value-of select="@Month"/>
                        </EndMonth>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:if test="not(preceding-sibling::*[1][self::Child and @Payment = $Payment])">
                <PP>
                    <Ps>
                        <xsl:copy-of select="$start-end"/>
                        <xsl:apply-templates select="current()"/>
                        <xsl:apply-templates select="following-sibling::*[1][self::Child and @Payment = $Payment]">
                            <xsl:with-param name="Payment" select="$Payment"/>
                        </xsl:apply-templates>
                    </Ps>
                </PP>
            </xsl:if>
        </xsl:for-each>
    </PPS>
</xsl:template>
<xsl:template match="Child">
    <xsl:param name="Payment"/>
    <P>
        <Amount>
            <xsl:value-of select="@Payment"/>
        </Amount>
        <startP>
            <xsl:value-of select="@No"/>
        </startP>
    </P>
    <xsl:apply-templates select="following-sibling::*[1][self::Child and @Payment = $Payment]">
        <xsl:with-param name="Payment" select="$Payment"/>
    </xsl:apply-templates>
</xsl:template>
<xsl:template match="Child" mode="month">
    <xsl:param name="Payment"/>
    <xsl:choose>
        <xsl:when test="following-sibling::*[1][self::Child and @Payment = $Payment]">
            <xsl:apply-templates select="following-sibling::*[1]" mode="month">
                <xsl:with-param name="Payment" select="$Payment"/>
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="@Month"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>