如何在XSLT 1.0中提取XML中PRODUCT DETAIL的去重值用于报表
问题描述
需要在发票报表中展示从XML获取的PRODUCT DETAIL去重值,数据库内部分订单的PRODUCT DETAIL存在重复。当前用XSLT 1.0获取到的结果为重复值:PRODUCT DETAIL : SHOES,SHOES,SHOES,SHOES,TROUSER,SHIRT
- 尝试使用
distinct-values()函数报错(XSLT 1.0不支持该函数) - 用
generate-id()仅得到第一个值SHOES
期望输出:PRODUCT DETAIL : SHOES , TROUSER , SHIRT
现有代码
查询语句
<query name="ORDER_DETAIL" value="SELECT ORDER_DETAIL.PRODUCT_DETAIL DETAIL, ORDER_DETAIL.PRODUCT_NAME NAME, FROM ORDER_DETAIL ORDER_DETAIL INNER JOIN PRODUCT_DETAIL DETAIL ON PRODUCT_DETAIL.ID = ORDER__DETAIL.ID WHERE ORDER_DETAIL.ID=? "
原XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" > <fo:table-cell padding=".5mm"> <fo:block font-size="10pt"> PRODUCT DETAIL <xsl:choose> <xsl:when test="//invoice_h/invoice_d/order_detail/@product_detail != '' "> <xsl:for-each select="//invoice_h/invoice_d/order_detail/@product_detail"> <xsl:value-of select="."/> </xsl:for-each> </xsl:when> </xsl:choose> </fo:block> </fo:table-cell>
尝试的generate-id()代码
<xsl:choose> <xsl:when test="//invoice_h/invoice_d/order_detail/@product_detail != '' "> <xsl:for-each select="//invoice_h/invoice_d/order_detail/@product_detail"> <xsl:if test="generate-id() = generate-id(//invoice_h/invoice_d/order_detail/@product_detail[. = current()][1])" > <xsl:value-of select="."/> <br /> </xsl:if> </xsl:for-each> </xsl:when> </xsl:choose>
解决方案:用Muenchian分组实现去重
XSLT 1.0没有内置的去重函数,标准做法是使用Muenchian分组,具体实现如下:
- 在XSLT根节点定义分组键,按
product_detail属性值分组:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" > <!-- 新增分组键 --> <xsl:key name="productDetailGroup" match="//invoice_h/invoice_d/order_detail/@product_detail" use="."/> <fo:table-cell padding=".5mm"> <fo:block font-size="10pt">PRODUCT DETAIL : <xsl:choose> <xsl:when test="//invoice_h/invoice_d/order_detail/@product_detail != '' "> <!-- 修改循环逻辑,只取每个分组的第一个节点 --> <xsl:for-each select="//invoice_h/invoice_d/order_detail/@product_detail[generate-id() = generate-id(key('productDetailGroup', .)[1])]"> <!-- 给非第一个值添加分隔符 --> <xsl:if test="position() > 1"> , </xsl:if> <xsl:value-of select="."/> </xsl:for-each> </xsl:when> <xsl:otherwise> 无 </xsl:otherwise> </xsl:choose> </fo:block> </fo:table-cell> </xsl:stylesheet>
代码说明
<xsl:key>:把所有product_detail属性按值分组,相同值的节点归为一组generate-id() = generate-id(key('productDetailGroup', .)[1]):确保只选中每个分组的第一个节点,实现去重<xsl:if test="position() > 1"> , </xsl:if>:在非第一个值前添加分隔符,匹配期望的输出格式
内容的提问来源于stack exchange,提问作者user21234409
相关产品推荐
相关产品推荐

