Объединение узлов XML на основе определенного значения ключа с использованием XSLT - PullRequest
0 голосов
/ 27 сентября 2019

Объединить узлы XML на основе значения ReferenceNumber

Как объединить запрос xml с выводом, приведенным ниже, с использованием XSLT на основе значения Key.По сути, XML-ответ должен быть объединен для ReferenceNumber вместе с соответствующими ProductCode и SecondaryDivision.Ниже приведен запрос и ожидаемый ответ.

Я пытался использовать следующий XSLT, но он не дал желаемого результата.

Ниже представлен XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="refNo" match="Envelope/Body/DocumentMetadataResponse" use="ReferenceNumber" />
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata" />
    <xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata[generate-id()=generate-id(key('refNo', DocumentMetadata/ReferenceNumber))]">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="DocumentMetadata">
        <xsl:copy>
            <xsl:apply-templates select="@*|ReferenceNumber" />
            <divisionses>
                <xsl:apply-templates select="key('refNo', ReferenceNumber)/DocumentMetadata" mode="divisions" />
            </divisionses>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="DocumentMetadata" mode="divisions">
        <Divisions>
            <xsl:apply-templates select="*[not(self::ReferenceNumber)]" />
        </Divisions>
    </xsl:template>
</xsl:stylesheet>

Входной XML

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
         <PageNumber>1</PageNumber>
         <PageSize>1000</PageSize>
         <TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
         <DocumentMetadata>
            <ReferenceNumber>Ref-01</ReferenceNumber>
            <SecondaryDivision>AT</SecondaryDivision>
            <ProductCode>Product-AT-01</ProductCode>
         </DocumentMetadata>
         <DocumentMetadata>
            <ReferenceNumber>Ref-01</ReferenceNumber>
            <SecondaryDivision>AT</SecondaryDivision>
            <ProductCode>Product-AT-02</ProductCode>
         </DocumentMetadata>
         <DocumentMetadata>
            <ReferenceNumber>Ref-01</ReferenceNumber>
            <SecondaryDivision>BE</SecondaryDivision>
            <ProductCode>Product-BE-01</ProductCode>
         </DocumentMetadata>
         <DocumentMetadata>
            <ReferenceNumber>Ref-02</ReferenceNumber>
            <SecondaryDivision>BS</SecondaryDivision>
            <ProductCode>Product-BS-01</ProductCode>
         </DocumentMetadata>
      </ns2:DocumentMetadataResponse>
   </soap:Body>
</soap:Envelope>

Ожидаемый выходной XML

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
         <PageNumber>1</PageNumber>
         <PageSize>1000</PageSize>
         <TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
         <DocumentMetadata>
            <ReferenceNumber>Ref-01</ReferenceNumber>
            <Divisions>
               <Division>
                  <SecondaryDivision>AT</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-AT-01</ProductCode>
                     </Product>
                     <Product>
                        <ProductCode>Product-AT-02</ProductCode>
                     </Product>
                  </Products>
               </Division>
               <Division>
                  <SecondaryDivision>BE</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-BE-01</ProductCode>
                     </Product>
                  </Products>
               </Division>
            </Divisions>
         </DocumentMetadata>
         <DocumentMetadata>
            <ReferenceNumber>Ref-02</ReferenceNumber>
            <Divisions>
               <Division>
                  <SecondaryDivision>BS</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-BS-01</ProductCode>
                     </Product>
                  </Products>
               </Division>
            </Divisions>
         </DocumentMetadata>
      </ns2:DocumentMetadataResponse>
   </soap:Body>
</soap:Envelope>

1 Ответ

0 голосов
/ 27 сентября 2019

Вы можете использовать этот шаблон XSLT-2.0 для выполнения этой работы.xsl:for-each-group выполняет два уровня группировки:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://www.example.com/mService">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ns2:DocumentMetadataResponse ">
        <xsl:copy>
            <xsl:apply-templates select="@*|* except DocumentMetadata" />
            <xsl:for-each-group select="DocumentMetadata" group-by="ReferenceNumber">
                <DocumentMetadata>
                    <ReferenceNumber><xsl:value-of select="current-grouping-key()" /></ReferenceNumber>
                    <Divisions>
                        <xsl:for-each-group select="current-group()" group-by="SecondaryDivision">
                            <Division>
                                <SecondaryDivision><xsl:value-of select="current-grouping-key()" /></SecondaryDivision>
                                <Products>
                                    <xsl:for-each select="current-group()">
                                        <Product>
                                            <ProductCode><xsl:value-of select="ProductCode" /></ProductCode>
                                        </Product>
                                    </xsl:for-each>
                                </Products>
                            </Division>
                        </xsl:for-each-group>
                    </Divisions>
                </DocumentMetadata>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Вывод:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
         <PageNumber>1</PageNumber>
         <PageSize>1000</PageSize>
         <TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
         <DocumentMetadata>
            <ReferenceNumber>Ref-01</ReferenceNumber>
            <Divisions>
               <Division>
                  <SecondaryDivision>AT</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-AT-01</ProductCode>
                     </Product>
                     <Product>
                        <ProductCode>Product-AT-02</ProductCode>
                     </Product>
                  </Products>
               </Division>
               <Division>
                  <SecondaryDivision>BE</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-BE-01</ProductCode>
                     </Product>
                  </Products>
               </Division>
            </Divisions>
         </DocumentMetadata>
         <DocumentMetadata>
            <ReferenceNumber>Ref-02</ReferenceNumber>
            <Divisions>
               <Division>
                  <SecondaryDivision>BS</SecondaryDivision>
                  <Products>
                     <Product>
                        <ProductCode>Product-BS-01</ProductCode>
                     </Product>
                  </Products>
               </Division>
            </Divisions>
         </DocumentMetadata>
      </ns2:DocumentMetadataResponse>
   </soap:Body>
</soap:Envelope>
...