使用 muenchian 分组创建具有不同异常的多个节点
creating multiple nodes with different exceptions with muenchian grouping
我正在尝试使用下面的示例 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,或者使用代码与我的参数不匹配的模式。
我基本上是在寻找 for-each where PackageTypeCode !=XX 之类的东西。
所以我想遍历所有 PackageTypeCodes,我在其中设置了为其创建产品的代码的参数。
然后是第二个,我将第一个参数中的“未使用”参数与@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 的所有东西以及我想添加的任何东西完成。未包含的那些,即 PC、XX、YY、ZZ 等应全部组合在 PC 下,数量等于 PC+XX+YY+ZZ 的数量,但在 1 个产品标签下。
<!--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>
<?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>
我建议您通过两步来简化问题:首先,将所有要组合在一起的代码重命名为 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>
我正在尝试使用下面的示例 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,或者使用代码与我的参数不匹配的模式。 我基本上是在寻找 for-each where PackageTypeCode !=XX 之类的东西。 所以我想遍历所有 PackageTypeCodes,我在其中设置了为其创建产品的代码的参数。 然后是第二个,我将第一个参数中的“未使用”参数与@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 的所有东西以及我想添加的任何东西完成。未包含的那些,即 PC、XX、YY、ZZ 等应全部组合在 PC 下,数量等于 PC+XX+YY+ZZ 的数量,但在 1 个产品标签下。
<!--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>
<?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>
我建议您通过两步来简化问题:首先,将所有要组合在一起的代码重命名为 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>