在解决客户对其XML转换的请求时,我遇到了一些麻烦。他们要求收到重复的发票行时,希望自动将重复行的值更改为发票行号序列中的下一个值,请参见下面的输入和预期输出。
输入:
<?xml version="1.0" encoding="UTF-8"?>
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>2</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>3</NumeroLinea>
</DettaglioLinee>
</DatiBeniServizi>
预期输出:
<Invoice>
<InvoiceDetail>
<InvoiceLineNumber>1</InvoiceLineNumber>
</InvoiceDetail>
<InvoiceDetail>
<InvoiceLineNumber>4</InvoiceLineNumber>
</InvoiceDetail>
<InvoiceDetail>
<InvoiceLineNumber>2</InvoiceLineNumber>
</InvoiceDetail>
<InvoiceDetail>
<InvoiceLineNumber>3</InvoiceLineNumber>
</InvoiceDetail>
</Invoice>
我尝试分组,但没有得到他们要求的结果,这听起来很简单,但我整天都在徒劳地解决问题。
欢迎任何帮助,感谢您的宝贵时间!
答案 0 :(得分:2)
假设每个重复项每次都增加1(因此第一个重复项是4,然后是下一个5),执行此操作的一种方法可能是使用递归模板,该模板依次处理每个项目并递增一个参数当发现重复项时。
要查找重复项,我不得不使用Muenchian分组,该分组通常在XSLT 1.0中使用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="invoices" match="DettaglioLinee" use="NumeroLinea" />
<xsl:variable name="max" select="max(/DatiBeniServizi/DettaglioLinee/NumeroLinea)" />
<xsl:template match="DatiBeniServizi">
<Invoice>
<xsl:apply-templates select="DettaglioLinee[1]" />
</Invoice>
</xsl:template>
<xsl:template match="DettaglioLinee">
<xsl:param name="incr" select="1" />
<xsl:variable name="isDistinct" select="generate-id() = generate-id(key('invoices', NumeroLinea)[1])" />
<InvoiceDetail>
<InvoiceLineNumber>
<xsl:value-of select="if ($isDistinct) then NumeroLinea else $max + $incr" />
</InvoiceLineNumber>
</InvoiceDetail>
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="incr" select="if ($isDistinct) then $incr else $incr + 1" />
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
如果重复项总是连续的(例如,您将没有1,2,1),则删除键的使用,并定义isDistinct
变量,如下所示:>
<xsl:variable name="isDistinct" select="not(NumeroLinea = preceding-sibling::*[1]/NumeroLinea)" />
编辑:如果您不担心数字是连续的(例如,可以有1、5、2、3),则只需将重复项的位置添加到最大值上,这样可以避免重复
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="invoices" match="DettaglioLinee" use="NumeroLinea" />
<xsl:variable name="max" select="max(/DatiBeniServizi/DettaglioLinee/NumeroLinea)" />
<xsl:template match="DatiBeniServizi">
<Invoice>
<xsl:apply-templates select="DettaglioLinee" />
</Invoice>
</xsl:template>
<xsl:template match="DettaglioLinee">
<xsl:variable name="isDistinct" select="generate-id() = generate-id(key('invoices', NumeroLinea)[1])" />
<InvoiceDetail>
<InvoiceLineNumber>
<xsl:value-of select="if ($isDistinct) then NumeroLinea else $max + position()" />
</InvoiceLineNumber>
</InvoiceDetail>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这是将分组问题与编号问题混合在一起。
此XSLT 1.0样式表
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kNumeroLineaByValue" match="NumeroLinea" use="." />
<xsl:variable name="vNumeroLineaDistinct"
select="//NumeroLinea[generate-id()=generate-id(key('kNumeroLineaByValue',.))]" />
<xsl:variable name="vNumeroLineaDistinctCount"
select="count($vNumeroLineaDistinct)" />
<xsl:variable name="vNumeroLineaLastValue">
<xsl:for-each select="$vNumeroLineaDistinct">
<xsl:sort data-type="number" order="descending" />
<xsl:if test="position()=1">
<xsl:value-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="NumeroLinea/text()">
<xsl:choose>
<xsl:when
test="count(..|$vNumeroLineaDistinct)!=$vNumeroLineaDistinctCount">
<xsl:variable name="vPosition">
<xsl:number level="any"
count="NumeroLinea[.=preceding::NumeroLinea]" />
</xsl:variable>
<xsl:value-of
select="$vPosition + $vNumeroLineaLastValue" />
</xsl:when>
<xsl:otherwise>
<xsl:copy />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
此输入
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>2</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>3</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>3</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>5</NumeroLinea>
</DettaglioLinee>
</DatiBeniServizi>
结果:
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>6</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>2</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>3</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>7</NumeroLinea>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>5</NumeroLinea>
</DettaglioLinee>
</DatiBeniServizi>
注意:分组进行重复数据删除,然后从起始值(所有不同值的最大值)开始编号