我正在尝试创建多个"产品";使用xsl:key进行分组,使用以下示例
<xsl:key name="product-by-pkg" match="GoodsItem" use="PackageTypeCode"
<xsl:for-each select="GoodsItem[count(. | key('product-by-pkg', PackageTypeCode)[1]) = 1]">
<product type="{PackageTypeCode}">
<quantity>
<!-- count current group -->
<xsl:value-of select="count(key('product-by-pkg', PackageTypeCode))" />
</quantity>
</product>
</xsl:for-each>
在这个源上
<GoodsItem>
<PackageTypeCode>PC</PackageTypeCode>
</GoodsItem>
<GoodsItem>
<PackageTypeCode>PE</PackageTypeCode>
</GoodsItem>
<GoodsItem>
<PackageTypeCode>PC</PackageTypeCode>
</GoodsItem>
<GoodsItem>
<PackageTypeCode>XX</PackageTypeCode>
</GoodsItem>
<GoodsItem>
<PackageTypeCode>OA</PackageTypeCode>
<GoodsItem>
<PackageTypeCode>OF</PackageTypeCode>
</GoodsItem>
<GoodsItem>
<PackageTypeCode>CW</PackageTypeCode>
</GoodsItem>
我想做的是使用上面的转换创建一个产品标签,其中PackageTypeCodes不是YY或XX,或者使用代码与我的参数不匹配的模式。我基本上是在寻找一个每个位置的PackageTypeCode=XX之类的事情。因此,我想循环遍历所有PackageTypeCodes,在那里我设置了要为其创建产品的Codes的参数。然后是第二个,我把";未使用的";在带有@type PC 的产品的第一个参数中
所以我的结果看起来像
<extraGoodsData>
<product type="PE">
<quantity>1</quantity>
</product>
<product type="OA">
<quantity>1</quantity>
</product>
<product type="OF">
<quantity>1</quantity>
</product>
<product type="CW">
<quantity>1</quantity>
</product>
</extraGoodsData>
我希望XX作为默认值计入PC,因此在第一次迭代中与我的参数不匹配的情况将在第二次迭代中使用,以创建
<product type="PC">
<!--quantity should be equal to the number of PC + non matching PackageTypeCodes in the first iteration-->
<quantity>3</quantity>
</product>
最后的结果就像这个
<extraGoodsData>
<product type="PE">
<quantity>1</quantity>
</product>
<product type="OA">
<quantity>1</quantity>
</product>
<product type="OF">
<quantity>1</quantity>
</product>
<product type="CW">
<quantity>1</quantity>
</product>
<!--number of PC PackageTypeCodes + non matching in the first count-->
<product type="PC">
<quantity>3</quantity>
</product>
</extraGoodsData>
这在XSLT1.0中可能吗?
编辑-------
所有与我想要的东西不匹配的packageTypeCodes,例如,对于所有与PE、OA、CW、OF相等的东西,以及我想添加到其中的任何东西,都应该执行for each。不包括的,即PC、XX、YY、ZZ等,应全部组合在PC下,数量等于PC+XX+YY+ZZ的数量,但在一个产品标签下。
<!--for PE OA OF CW-->
<xsl:for-each select="GoodsItem[count(. | key('product-by-pkg', PackageTypeCode)[1]) = 1]">
<product type="{PackageTypeCode}">
<quantity>
<!-- count current group -->
<xsl:value-of select="count(key('product-by-pkg', PackageTypeCode))" />
</quantity>
</product>
</xsl:for-each>
<!--for PC,XX,ZZ,YY etc-->
<xsl:for-each select="GoodsItem[count(. | key('product-by-pkg', PackageTypeCode)[1]) = 1]">
<product type="PC">
<quantity>
<xsl:value-of select="count(key('product-by-pkg', PackageTypeCode))" />
</quantity>
</product>
</xsl:for-each>
我建议您通过两个步骤来简化问题:首先,将所有要分组的代码重命名为PC
。然后将Muenchian分组应用于结果:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="pkg" match="package" use="."/>
<xsl:template match="/root">
<xsl:variable name="packages">
<xsl:for-each select="GoodsItem">
<package>
<xsl:choose>
<xsl:when test="PackageTypeCode='PE' or PackageTypeCode='OA' or PackageTypeCode='OF' or PackageTypeCode='CW'">
<xsl:value-of select="PackageTypeCode"/>
</xsl:when>
<xsl:otherwise>PC</xsl:otherwise>
</xsl:choose>
</package>
</xsl:for-each>
</xsl:variable>
<output>
<xsl:for-each select="exsl:node-set($packages)/package[count(. | key('pkg', .)[1]) = 1]">
<product type="{.}">
<quantity>
<!-- count current group -->
<xsl:value-of select="count(key('pkg', .))" />
</quantity>
</product>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
演示:https://xsltfiddle.liberty-development.net/a9HjZJ
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="product-by-pkg" match="GoodsItem" use="PackageTypeCode"/>
<!-- I modified the code to handle dynamic exceptions. You
need to created the exceptionList in this format from what ever source you have. -->
<xsl:variable name="exceptions">
<xsl:element name="PackageTypeCode">XX</xsl:element>
<xsl:element name="PackageTypeCode">YY</xsl:element>
</xsl:variable>
<!-- Use whatever namespace you have set up. I am using msxml. -->
<xsl:variable name="exceptionList" select="msxml:node-set($exceptions)"/>
<!-- I added root to you xml. Use whatever parent node you have. -->
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="GoodsItem[generate-id(.) = generate-id(key('product-by-pkg', PackageTypeCode)[not(PackageTypeCode = $exceptionList/PackageTypeCode)][1])]">
<xsl:element name="product">
<xsl:attribute name="type">
<xsl:value-of select="PackageTypeCode"/>
</xsl:attribute>
<xsl:element name="quantity">
<xsl:choose>
<xsl:when test="PackageTypeCode = 'PC'">
<xsl:value-of select="count(key('product-by-pkg', PackageTypeCode)) + count(key('product-by-pkg', $exceptionList/PackageTypeCode))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(key('product-by-pkg', PackageTypeCode))" />
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>