XSLT如何循环InvoiceLine,将关联Charge与Quantity同行输出?
XML/XSLT关联Charge与Quantity配对输出解决方案
问题场景
现有如下XML结构:
<cac:InvoiceLine> <cbc:ID>1</cbc:ID> <cbc:Note>Some remark text</cbc:Note> <cbc:Note>Charge: 1234567*</cbc:Note> <cbc:Note>Quantity: 1000*</cbc:Note> <cbc:Note>Charge: 987654*</cbc:Note> <cbc:Note>Quantity: 5000*</cbc:Note> ... </cac:InvoiceLine>
其中Charge与Quantity按顺序配对关联(如Charge: 1234567*对应Quantity: 1000*),需要将每对数据输出为以下单行格式:
1000 kg Charge 1234567
5000 kg Charge 987654
用户原代码会为每个<cbc:Note>单独换行,无法实现配对输出:
<xsl:for-each select="./cbc:Note"> <xsl:choose> <xsl:when test="contains(.,'Charge:')"> <xsl:value-of select="substring-before(substring-after(.,'Charge:'),'*')"/> <br /> </xsl:when> <xsl:when test="contains(.,'Menge:')"> <xsl:value-of select="substring-before(substring-after(.,'Quantity:'),'*')"/> <br /> </xsl:when> <xsl:otherwise> <xsl:value-of select="."/> <br /> </xsl:otherwise> </xsl:choose> </xsl:for-each>
解决思路
思路1:遍历Charge节点,关联后续首个Quantity节点
利用节点的顺序关系,遍历所有Charge类型的<cbc:Note>,然后获取每个Charge节点之后的第一个Quantity节点,实现配对输出:
<!-- 遍历所有包含Charge的Note节点 --> <xsl:for-each select="cbc:Note[contains(., 'Charge:')]"> <!-- 提取Charge的数值 --> <xsl:variable name="chargeVal" select="substring-before(substring-after(., 'Charge: '), '*')"/> <!-- 获取当前Charge节点之后第一个Quantity节点的数值 --> <xsl:variable name="qtyVal" select="following-sibling::cbc:Note[contains(., 'Quantity: ')][1]/substring-before(substring-after(., 'Quantity: '), '*')"/> <!-- 输出配对后的单行内容 --> <xsl:value-of select="concat($qtyVal, ' kg Charge ', $chargeVal)"/> <br/> </xsl:for-each>
思路2:按位置索引分组配对
如果Charge和Quantity是严格交替出现的,可以通过位置索引直接配对对应位置的节点:
<!-- 遍历所有Charge节点 --> <xsl:for-each select="cbc:Note[contains(., 'Charge:')]"> <xsl:variable name="currentIndex" select="position()"/> <!-- 提取对应位置的Quantity节点数值 --> <xsl:variable name="qtyVal" select="../cbc:Note[contains(., 'Quantity:')][$currentIndex]/substring-before(substring-after(., 'Quantity: '), '*')"/> <xsl:variable name="chargeVal" select="substring-before(substring-after(., 'Charge: '), '*')"/> <xsl:value-of select="concat($qtyVal, ' kg Charge ', $chargeVal)"/> <br/> </xsl:for-each>
补充优化
- 注意文本匹配的空格:原XML中
Charge:和Quantity:带有空格,提取数值时要保留该空格,避免获取到带空格的无效值。 - 若存在未配对的Charge/Quantity节点,可以添加判断逻辑避免输出空内容:
<xsl:if test="$qtyVal != '' and $chargeVal != ''"> <xsl:value-of select="concat($qtyVal, ' kg Charge ', $chargeVal)"/> <br/> </xsl:if>
内容的提问来源于stack exchange,提问作者dns_nx
相关产品推荐
相关产品推荐

