输入xml按每个元素的id排序,我正在检查当前节点是否具有与前一个兄弟相同的id。如果它们是相同的,那么我想从xml中删除(不显示)当前节点并将其一些值添加到该兄弟节点。如果id匹配,检查当前节点与任何先前节点并执行相同的逻辑将非常有用。
这是输入xml:
<?xml version="1.0"?>
<transactions>
<transaction>
<name>Test Entry</name>
<id>123</id>
<line_memo>memo1</line_memo>
<amount>5</amount>
</transaction>
<transaction>
<name>Test 1</name>
<id>123</id>
<line_memo>memo2</line_memo>
<amount>10</amount>
</transaction>
<transaction>
<name>Test 2</name>
<id>123</id>
<line_memo>memo3</line_memo>
<amount>15</amount>
</transaction>
<transaction>
<name>Test 3</name>
<id>1235</id>
<line_memo>0123456789</line_memo>
<amount>30</amount>
</transaction>
</transactions>
我的XSLT - 我一直在尝试应用模板和参数。:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="transactions">
<transactions>
<xsl:for-each select="transaction">
<xsl:variable name="name" select="adjustment_flag"/>
<xsl:variable name="id" select="id"/>
<xsl:variable name="amount" select="amount"/>
<xsl:variable name="line_memo" select="control_amount"/>
<xsl:variable name="invoice_date" select="invoice_number"/>
<xsl:choose>
<xsl:when test="(position() > 1)">
<xsl:choose>
<xsl:when test="preceding-sibling::transaction[id = $id]">
<transaction>
<xsl:apply-templates select="preceding-sibling::transaction/line_memo">
<xsl:with-param name="newMemo" select="line_memo"/>
</xsl:apply-templates>
<xsl:apply-templates select="preceding-sibling::transaction/amount">
<xsl:with-param name="newAmount" select="amount"/>
</xsl:apply-templates>
<name><xsl:value-of select="name"/></name>
<id><xsl:value-of select="id"/></id>
<!--<line_memo><xsl:value-of select="line_memo"/></line_memo>
<amount><xsl:value-of select="amount"/></amount>-->
</transaction>
</xsl:when>
<xsl:otherwise>
<transaction>
<name><xsl:value-of select="name"/></name>
<id><xsl:value-of select="id"/></id>
<line_memo><xsl:value-of select="line_memo"/></line_memo>
<amount><xsl:value-of select="amount"/></amount>
</transaction>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<transaction>
<name><xsl:value-of select="name"/></name>
<id><xsl:value-of select="id"/></id>
<line_memo><xsl:value-of select="line_memo"/></line_memo>
<amount><xsl:value-of select="amount"/></amount>
</transaction>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</transactions>
</xsl:template>
<xsl:template match="line_memo">
<xsl:param name="newMemo"/>
<new_memo><xsl:value-of select="concat(line_memo, '|', $newMemo)"/></new_memo>
</xsl:template>
<xsl:template match="amount">
<xsl:param name="newAmount"/>
<new_amount><xsl:value-of select="amount + $newAmount"/></new_amount>
</xsl:template>
</xsl:stylesheet>
期望的输出:
<?xml version="1.0"?>
<transactions>
<transaction>
<name>Test Entry</name>
<id>123</id>
<line_memo>memo1|memo2|memo3</line_memo>
<amount>30</amount>
</transaction>
<transaction>
<name>Test 3</name>
<id>1235</id>
<line_memo>0123456789</line_memo>
<amount>30</amount>
</transaction>
</transactions>
我的输出使用上面的样式表:
<?xml version="1.0" encoding="utf-16"?>
<transactions>
<transaction>
<name>Test Entry</name>
<id>123</id>
<line_memo>memo1</line_memo>
<amount>5</amount>
</transaction>
<transaction>
<new_memo>|memo2</new_memo>
<new_amount>NaN</new_amount>
<name>Test 1</name>
<id>123</id>
</transaction>
<transaction>
<new_memo>|memo3</new_memo>
<new_memo>|memo3</new_memo>
<new_amount>NaN</new_amount>
<new_amount>NaN</new_amount>
<name>Test 2</name>
<id>123</id>
</transaction>
<transaction>
<name>Test 3</name>
<id>1235</id>
<line_memo>0123456789</line_memo>
<amount>30</amount>
</transaction>
</transactions>
最终输出包含一个带有123
id的元素,并将金额相加并将备注字段与|
分隔符连接起来。
在我的样式表中,我添加了apply-templates但是我收到了一个错误,它说
Required item type of @select attribute of xsl:apply-templates is node(); supplied value has item type xs:string
。
如何修改前面的兄弟元素并省略当前节点?
答案 0 :(得分:2)
不要在“修改”已经输出的任何内容方面考虑它。您要在此处执行的操作是为共享相同ID的输入transaction
元素的每个组创建一个输出transaction
元素。由于您使用的是XSLT 2.0,因此for-each-group
和separator
上的value-of
属性很容易实现:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:template match="/*">
<xsl:copy>
<!-- process all input transactions with the same id as a group -->
<xsl:for-each-group select="transaction" group-by="id">
<transaction>
<!-- copy name and id from the first instance -->
<xsl:sequence select="name, id" />
<!-- join all the memos in the group with | - if there's only one
then there will be no separator -->
<line_memo>
<xsl:value-of select="current-group()/line_memo" separator="|" />
</line_memo>
<!-- sum the amounts -->
<amount>
<xsl:value-of select="sum(current-group()/amount)" />
</amount>
</transaction>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用Saxon 9 HE对样本输入运行时,会生成所需的输出:
<?xml version="1.0" encoding="UTF-8"?>
<transactions>
<transaction>
<name>Test Entry</name>
<id>123</id>
<line_memo>memo1|memo2|memo3</line_memo>
<amount>30</amount>
</transaction>
<transaction>
<name>Test 3</name>
<id>1235</id>
<line_memo>0123456789</line_memo>
<amount>30</amount>
</transaction>
</transactions>