создание нескольких узлов с разными исключениями с мюнхской группировкой - PullRequest
0 голосов
/ 04 августа 2020

Я пытаюсь создать несколько «продуктов», используя группировку с помощью ключа xsl:, используя приведенный ниже пример

<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 типа вещей. Итак, я хочу l oop через все PackageTypeCodes, где я устанавливаю аргумент, для каких кодов создавать продукты. А затем второй, где я объединяю «неиспользованные» в первом аргументе продукта с @type P C

, чтобы мой результат выглядел примерно так:

 <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 учитывался в P C по умолчанию, поэтому несоответствие моим аргументам в первой итерации должно использоваться во второй для создания

 <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?

EDIT -------

все packageTypeCodes, которые не соответствуют тому, что я хочу, поэтому например, for each должно выполняться для всего, что равно PE, OA, CW, OF и всему, что я хочу добавить к этому. Те, которые не включены, например, P C, XX, YY, ZZ и c, должны быть объединены под P C и в количестве, равном количеству 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 ]

1 голос
/ 04 августа 2020

Я бы посоветовал вам упростить задачу, сделав два прохода: во-первых, переименуйте все коды, которые вы хотите сгруппировать, в PC. Затем примените к результату мюнхианскую группировку:

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

0 голосов
/ 04 августа 2020
<?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>
...