以下是源XML:
<CellData>
<Cell CellOrdinal="0">
<Value>actual</Value>
<FmtValue>actual</FmtValue>
</Cell>
<Cell CellOrdinal="1">
<Value>630961942</Value>
<FmtValue>630961942</FmtValue>
</Cell>
<Cell CellOrdinal="2">
<Value>2.045711422E7</Value>
<FmtValue>20457114.2200</FmtValue>
</Cell>
<Cell CellOrdinal="3">
<Value>9.997105219639378E1</Value>
<FmtValue>99.9711</FmtValue>
</Cell>
<Cell CellOrdinal="4">
<Value>3.33E1</Value>
<FmtValue>33.0000</FmtValue>
</Cell>
<Cell CellOrdinal="5">
<Value>2.046303782E7</Value>
<FmtValue>20463037.8200</FmtValue>
</Cell>
<Cell CellOrdinal="6">
<Value>deposit</Value>
<FmtValue>deposit</FmtValue>
</Cell>
<Cell CellOrdinal="7">
<Value>144783359</Value>
<FmtValue>144783359</FmtValue>
</Cell>
<Cell CellOrdinal="8">
<Value>2.1388E2</Value>
<FmtValue>213.8800</FmtValue>
</Cell>
<Cell CellOrdinal="9">
<Value>1.0452016063370595E-3</Value>
<FmtValue>0.0010</FmtValue>
</Cell>
<Cell CellOrdinal="10">
<Value>6.67E1</Value>
<FmtValue>67.0000</FmtValue>
</Cell>
<Cell CellOrdinal="11">
<Value>2.046303782E7</Value>
<FmtValue>20463037.8200</FmtValue>
</Cell>
<Cell CellOrdinal="12">
<Value>deposit</Value>
<FmtValue>deposit</FmtValue>
</Cell>
<Cell CellOrdinal="13">
<Value>304011203</Value>
<FmtValue>304011203</FmtValue>
</Cell>
<Cell CellOrdinal="14">
<Value>5.70972E3</Value>
<FmtValue>5709.7200</FmtValue>
</Cell>
<Cell CellOrdinal="15">
<Value>2.7902601999882342E-2</Value>
<FmtValue>0.0279</FmtValue>
</Cell>
<Cell CellOrdinal="16">
<Value>6.67E1</Value>
<FmtValue>67.0000</FmtValue>
</Cell>
<Cell CellOrdinal="17">
<Value>2.046303782E7</Value>
<FmtValue>20463037.8200</FmtValue>
</Cell>
</CellData>
此列表包含6列表格数据。数据按第1列排序,包含"type",按顺序排列:actual
、accumulation
、deposit
,但有些可能根本不存在(示例中为累加)。即它实际上包含以下数据:
contract_type contract_id sum percentage contract_type_percentage balance_total
actual 630961942 20457114.2200 99.9711 33.0000 20463037.8200
deposit 144783359 213.8800 0.0010 67.0000 20463037.8200
deposit 304011203 5709.7200 0.0279 67.0000 20463037.8200
以下是所需的XML输出(基于示例):
<body>
<actual_accounts>
<actual_account>
<contract_id>630961942</contract_id>
<sum>20457114.2200</sum>
<percentage>99.9711</percentage>
</actual_account>
<actual_percentage>33.0000</actual_percentage>
</actual_accounts>
<accumulation_accounts>
<accumulation_percentage>0</accumulation_percentage>
</accumulation_accounts>
<deposits>
<deposit>
<contract_id>144783359</contract_id>
<sum>213.8800</sum>
<percentage>0.0010</percentage>
</deposit>
<deposit>
<contract_id>304011203</contract_id>
<sum>5709.7200</sum>
<percentage>0.0279</percentage>
</deposit>
<deposit_percentage>67.0000</deposit_percentage>
</deposits>
<balance_total>20463037.8200</balance_total>
</body>
其中*_percentage
标记应包含关联*
集合中任意行的第5列的值。
到目前为止,我得到的是:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" method="xml" version="1.0"/>
<xsl:template match="/">
<body>
<actual_accounts>
<xsl:apply-templates select="//Cell">
<xsl:with-param name="cellType" select="'actual_accounts'"/>
</xsl:apply-templates>
<actual_percentage>0</actual_percentage>
</actual_accounts>
<accumulation_accounts>
<xsl:apply-templates select="//Cell">
<xsl:with-param name="cellType" select="'accumulation_accounts'"/>
</xsl:apply-templates>
<accumulation_percentage>0</accumulation_percentage>
</accumulation_accounts>
<deposits>
<xsl:apply-templates select="//Cell">
<xsl:with-param name="cellType" select="'deposits'"/>
</xsl:apply-templates>
<deposit_percentage>0</deposit_percentage>
</deposits>
<xsl:choose>
<xsl:when test="count(CellData/Cell) >= 6">
<balance_total>
<xsl:value-of select="CellData/Cell[6]/FmtValue"/>
</balance_total>
</xsl:when>
<xsl:otherwise>
<balance_total>0</balance_total>
</xsl:otherwise>
</xsl:choose>
</body>
</xsl:template>
<xsl:template match="//Cell">
<xsl:param name="cellType"/>
<xsl:if test="@CellOrdinal mod 6 = 0">
<xsl:variable name="contract_type" select="FmtValue"/>
<xsl:variable name="contract_id" select="@CellOrdinal + 2"/>
<xsl:variable name="sum" select="@CellOrdinal + 3"/>
<xsl:variable name="percentage" select="@CellOrdinal + 4"/>
<xsl:variable name="type_percentage" select="@CellOrdinal + 5"/>
<xsl:variable name="balance_total" select="@CellOrdinal + 6"/>
<xsl:if test="$contract_type = 'actual' and $cellType = ('actual_accounts')">
<actual_account>
<contract_id>
<xsl:value-of select="parent::CellData/Cell[$contract_id]/FmtValue"/>
</contract_id>
<sum>
<xsl:value-of select="parent::CellData/Cell[$sum]/FmtValue"/>
</sum>
<percentage>
<xsl:value-of select="parent::CellData/Cell[$percentage]/FmtValue"/>
</percentage>
</actual_account>
</xsl:if>
<xsl:if test="$contract_type = 'accumulation' and $cellType = ('accumulation_accounts')">
<accumulation_account>
<contract_id>
<xsl:value-of select="parent::CellData/Cell[$contract_id]/FmtValue"/>
</contract_id>
<sum>
<xsl:value-of select="parent::CellData/Cell[$sum]/FmtValue"/>
</sum>
<percentage>
<xsl:value-of select="parent::CellData/Cell[$percentage]/FmtValue"/>
</percentage>
</accumulation_account>
</xsl:if>
<xsl:if test="$contract_type = 'deposit' and $cellType = 'deposits'">
<deposit>
<contract_id>
<xsl:value-of select="parent::CellData/Cell[$contract_id]/FmtValue"/>
</contract_id>
<sum>
<xsl:value-of select="parent::CellData/Cell[$sum]/FmtValue"/>
</sum>
<percentage>
<xsl:value-of select="parent::CellData/Cell[$percentage]/FmtValue"/>
</percentage>
</deposit>
</xsl:if>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
除了其*_percentage
标签之外,它们什么都做。。我仅限于XSLT1.0。
用最终答案更新:对Maesto13解决方案进行小修复,仅适用于MSXML4.0+、.NET1.0+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt" extension-element-prefixes="msxml">
<xsl:output indent="yes" omit-xml-declaration="yes" method="xml" version="1.0"/>
<xsl:key name="CellGroup" use="@CellOrdinal - (@CellOrdinal mod 6)" match="CellData/Cell"/>
<xsl:template match="CellData">
<xsl:variable name="Cells">
<xsl:apply-templates select="Cell[generate-id() = generate-id(key('CellGroup', @CellOrdinal - (@CellOrdinal mod 6))[1])]" mode="group"/>
</xsl:variable>
<body>
<actual_accounts>
<xsl:for-each select="msxml:node-set($Cells)/Cell[contract-type='actual']">
<actual_account>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</actual_account>
</xsl:for-each>
<xsl:variable name="type_percentage" select="msxml:node-set($Cells)/Cell[contract-type='actual'][1]/contract-type-percentage[1]"></xsl:variable>
<xsl:choose>
<xsl:when test="boolean($type_percentage)">
<actual_percentage><xsl:value-of select="$type_percentage"/></actual_percentage>
</xsl:when>
<xsl:otherwise>
<actual_percentage>0</actual_percentage>
</xsl:otherwise>
</xsl:choose>
</actual_accounts>
<accumulation_accounts>
<xsl:for-each select="msxml:node-set($Cells)/Cell[contract-type='accumulation']">
<accumulation_account>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</accumulation_account>
</xsl:for-each>
<xsl:variable name="type_percentage" select="msxml:node-set($Cells)/Cell[contract-type='accumulation'][1]/contract-type-percentage[1]"></xsl:variable>
<xsl:choose>
<xsl:when test="boolean($type_percentage)">
<accumulation_percentage><xsl:value-of select="$type_percentage"/></accumulation_percentage>
</xsl:when>
<xsl:otherwise>
<accumulation_percentage>0</accumulation_percentage>
</xsl:otherwise>
</xsl:choose>
</accumulation_accounts>
<deposits>
<xsl:for-each select="msxml:node-set($Cells)/Cell[contract-type='deposit']">
<deposit>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</deposit>
</xsl:for-each>
<xsl:variable name="type_percentage" select="msxml:node-set($Cells)/Cell[contract-type='deposit'][1]/contract-type-percentage[1]"></xsl:variable>
<xsl:choose>
<xsl:when test="boolean($type_percentage)">
<deposit_percentage><xsl:value-of select="$type_percentage"/></deposit_percentage>
</xsl:when>
<xsl:otherwise>
<deposit_percentage>0</deposit_percentage>
</xsl:otherwise>
</xsl:choose>
</deposits>
<xsl:variable name="total" select="msxml:node-set($Cells)/Cell[1]/balance-total"></xsl:variable>
<xsl:choose>
<xsl:when test="boolean($total)">
<balance_total>
<xsl:value-of select="$total"/>
</balance_total>
</xsl:when>
<xsl:otherwise><balance_total>0</balance_total></xsl:otherwise>
</xsl:choose>
</body>
</xsl:template>
<xsl:template match="Cell" mode="group">
<Cell>
<xsl:variable name="Cells" select="key('CellGroup', @CellOrdinal - (@CellOrdinal mod 6))"/>
<contract-type><xsl:value-of select="$Cells[1]/FmtValue"/></contract-type>
<contract-id><xsl:value-of select="$Cells[2]/FmtValue"/></contract-id>
<sum><xsl:value-of select="$Cells[3]/FmtValue"/></sum>
<percentage><xsl:value-of select="$Cells[4]/FmtValue"/></percentage>
<contract-type-percentage><xsl:value-of select="$Cells[5]/FmtValue"/></contract-type-percentage>
<balance-total><xsl:value-of select="$Cells[6]/FmtValue"/></balance-total>
</Cell>
</xsl:template>
</xsl:stylesheet>
我更喜欢两步转换,先将数据收集到变量中。当涉及大量数据时,可能需要重新考虑。下面是一个xslt。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" method="xml" version="1.0"/>
<xsl:key name="CellGroup" use="@CellOrdinal - (@CellOrdinal mod 6)" match="CellData/Cell"/>
<xsl:template match="CellData">
<xsl:variable name="Cells">
<xsl:apply-templates select="Cell[generate-id() = generate-id(key('CellGroup', @CellOrdinal - (@CellOrdinal mod 6))[1])]" mode="group"/>
</xsl:variable>
<body>
<actual_accounts>
<xsl:for-each select="$Cells/Cell[contract-type='actual']">
<actual_account>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</actual_account>
</xsl:for-each>
<actual_percentage><xsl:value-of select="$Cells/Cell[contract-type='actual'][1]/contract-type-percentage"/></actual_percentage>
</actual_accounts>
<accumulation_accounts>
<xsl:for-each select="$Cells/Cell[contract-type='accumulation']">
<accumulation_account>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</accumulation_account>
</xsl:for-each>
<accumulation_percentage><xsl:value-of select="$Cells/Cell[contract-type='accumulation'][1]/contract-type-percentage[1]"/></accumulation_percentage>
</accumulation_accounts>
<deposits>
<xsl:for-each select="$Cells/Cell[contract-type='deposit']">
<deposit>
<xsl:copy-of select="contract-type"/>
<xsl:copy-of select="sum"/>
<xsl:copy-of select="percentage"/>
</deposit>
</xsl:for-each>
<deposit_percentage><xsl:value-of select="$Cells/Cell[contract-type='deposit'][1]/contract-type-percentage[1]"/></deposit_percentage>
</deposits>
<balance_total><xsl:value-of select="$Cells/Cell[1]/balance-total"/></balance_total>
</body>
</xsl:template>
<xsl:template match="Cell" mode="group">
<Cell>
<xsl:variable name="Cells" select="key('CellGroup', @CellOrdinal - (@CellOrdinal mod 6))"/>
<contract-type><xsl:value-of select="$Cells[1]/FmtValue"/></contract-type>
<contract-id><xsl:value-of select="$Cells[2]/FmtValue"/></contract-id>
<sum><xsl:value-of select="$Cells[3]/FmtValue"/></sum>
<percentage><xsl:value-of select="$Cells[4]/FmtValue"/></percentage>
<contract-type-percentage><xsl:value-of select="$Cells[5]/FmtValue"/></contract-type-percentage>
<balance-total><xsl:value-of select="$Cells[6]/FmtValue"/></balance-total>
</Cell>
</xsl:template>
</xsl:stylesheet>
我得到的输出如下:
<body>
<actual_accounts>
<actual_account>
<contract-type>actual</contract-type>
<sum>20457114.2200</sum>
<percentage>99.9711</percentage>
</actual_account>
<actual_percentage>33.0000</actual_percentage>
</actual_accounts>
<accumulation_accounts>
<accumulation_percentage></accumulation_percentage>
</accumulation_accounts>
<deposits>
<deposit>
<contract-type>deposit</contract-type>
<sum>213.8800</sum>
<percentage>0.0010</percentage>
</deposit>
<deposit>
<contract-type>deposit</contract-type>
<sum>5709.7200</sum>
<percentage>0.0279</percentage>
</deposit>
<deposit_percentage>67.0000</deposit_percentage>
</deposits>
<balance_total>20463037.8200</balance_total>
</body>