使用muenchian分组创建具有不同异常的多个节点

时间:2020-08-04 10:50:55

标签: xml xslt xslt-1.0

我正在尝试通过以下示例使用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,在其中我设置要为其创建产品的代码的参数。 然后是第二个,我将第一个参数中的“未使用”组合到具有@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的所有东西以及我想要添加的所有东西执行针对每个的packageTypeCodes。那些未包含的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>

2 个答案:

答案 0 :(得分:1)

我建议您通过两次传递来简化问题:首先,将要分组在一起的所有代码重命名为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

答案 1 :(得分:0)

<?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>
相关问题