我有以下xml
<toPay>
<Pay>
<amount>1111</amount>
<accountNumber>223128987</accountNumber>
<payType>PAYROLL</payType>
</Pay>
<Pay>
<amount>2222</amount>
<accountNumber>123128987</accountNumber>
<payType>PAYROLL</payType>
</Pay>
<Pay>
<amount>333</amount>
<accountNumber>645032</accountNumber>
<payType>MAIN</payType>
</Pay>
我需要这种格式的输出:
<root>
<element>
<amount>1111</amount>
<accountNumber>223128987</accountNumber>
</element>
<element>
<amount>2222</amount>
<accountNumber>223128987</accountNumber>
</element>
<element>
<amount></amount>
<accountNumber></accountNumber>
</element>
<element>
<amount></amount>
<accountNumber></accountNumber>
</element>
我写了以下代码:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="groups" match="payType" use="." />
<xsl:template match="/toPay/Pay">
<root>
<xsl:apply-templates select="payType[generate-id() = generate-id(key('groups', .)[1])]" />
</root>
</xsl:template>
<xsl:template match="payType">
<xsl:variable name="currentGroup" select="." />
<xsl:if test="$currentGroup = 'PAYROLL'">
<xsl:for-each select="key('groups', $currentGroup)">
<element>
<xsl:if test="position() = 1">
<amount>
<xsl:value-of select="../amount" />
</amount>
<accountNumber>
<xsl:value-of select="../accountNumber" />
</accountNumber>
</xsl:if>
<xsl:if test="position() = 2">
<amount>
<xsl:value-of select="../amount" />
</amount>
<accountNumber>
<xsl:value-of select="../accountNumber" />
</accountNumber>
</xsl:if>
</element>
</xsl:for-each>
</xsl:if>
</xsl:template>
但我面临的问题是 - 我无法访问paytype -PAYROLL的分组节点。我知道的唯一方法是使用position,但我要求总是在输出中输入4个元素节点,无论源xml中PAYtype -PAYROLL的节点是否存在。 如果存在,则填充相同eeds的值,如果不存在,则填充没有值的xml标记。
非常感谢任何帮助 - xslt 1.0或2.0。
答案 0 :(得分:1)
如果我理解你的解释,你可以做一些非常简单的事 - 即使有点原始:
<xsl:template match="/toPay">
<xsl:variable name="payroll" select="Pay[payType='PAYROLL']" />
<root>
<element>
<amount>
<xsl:value-of select="$payroll[1]/amount" />
</amount>
<accountNumber>
<xsl:value-of select="$payroll[1]/accountNumber" />
</accountNumber>
</element>
<element>
<amount>
<xsl:value-of select="$payroll[2]/amount" />
</amount>
<accountNumber>
<xsl:value-of select="$payroll[2]/accountNumber" />
</accountNumber>
</element>
<element>
<amount>
<xsl:value-of select="$payroll[3]/amount" />
</amount>
<accountNumber>
<xsl:value-of select="$payroll[3]/accountNumber" />
</accountNumber>
</element>
<element>
<amount>
<xsl:value-of select="$payroll[4]/amount" />
</amount>
<accountNumber>
<xsl:value-of select="$payroll[4]/accountNumber" />
</accountNumber>
</element>
</root>
</xsl:template>
我认为没有要求对任何事情进行分组。
这是一个稍微优雅的版本:
XSLT 2.0
<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="*"/>
<xsl:template match="/toPay">
<xsl:variable name="payroll" select="Pay[payType='PAYROLL']" />
<root>
<xsl:apply-templates select="$payroll"/>
<xsl:for-each select="1 to 4 - count($payroll)">
<element>
<amount/>
<accountNumber/>
</element>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="Pay">
<element>
<xsl:copy-of select="amount, accountNumber"/>
</element>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
我也认为不需要分组,如果你想为那些不存在的元素输出空元素,那么使用XSLT 2.0可以使用
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="toPay">
<root>
<xsl:variable name="payroll" select="Pay[payType = 'PAYROLL']"/>
<xsl:apply-templates select="$payroll"/>
<xsl:for-each select="(count($payroll) + 1) to 4">
<element>
<amount></amount>
<accountNumber></accountNumber>
</element>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="Pay">
<element>
<xsl:apply-templates select="* except payType"/>
</element>
</xsl:template>
</xsl:transform>