Группировка / объединение XSLT - два разных узла в один - PullRequest
0 голосов
/ 11 февраля 2020

Борьба с преобразованием xslt. В основном объединение двух разных узлов на основе ключа (кода страны), поэтому ввод xml состоит из двух частей.

If from part 1, country is found in part 2,
result = found

if from part 1, country is not found in part 2,
 result = new 

if from part 2, country is not found in part1,
 result = not found

Ввод XML -

<Root>
    <SomeData/>
    <COUNTRIES>
        <VALID_COUNTRY>
            <COUNTRY>DK</COUNTRY>
            <LANGUAGE>DANISH</LANGUAGE>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>SE</COUNTRY>
            <LANGUAGE>SWEDISH</LANGUAGE>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>CA</COUNTRY>
            <LANGUAGE>ENGLISH</LANGUAGE>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>US</COUNTRY>
            <LANGUAGE>ENGLISH</LANGUAGE>
        </VALID_COUNTRY>
    </COUNTRIES>
    <SomeOtherData/>
    <DATA>
        <FURTHER>
            <CountryInfo>
                <Country>DK</Country>
            </CountryInfo>
            <CountryInfo>
                <Country>US</Country>
            </CountryInfo>
            <CountryInfo>
                <Country>UK</Country>
            </CountryInfo>          
            <CountryInfo>
                <Country>AU</Country>
            </CountryInfo>  
        </FURTHER>
    </DATA>
</Root>

Ввод XML

<Root>
    <SomeData/>
    <COUNTRIES>
        <VALID_COUNTRY>
            <COUNTRY>DK</COUNTRY>
            <LANGUAGE>DANISH</LANGUAGE>
            <FOUND>YES</FOUND>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>SE</COUNTRY>
            <LANGUAGE>SWEDISH</LANGUAGE>
            <FOUND>NEW COUNTRY</FOUND>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>CA</COUNTRY>
            <LANGUAGE>ENGLISH</LANGUAGE>
            <FOUND>NEW COUNTRY</FOUND>
        </VALID_COUNTRY>
        <VALID_COUNTRY>
            <COUNTRY>US</COUNTRY>
            <LANGUAGE>ENGLISH</LANGUAGE>
            <FOUND>YES</FOUND>
        </VALID_COUNTRY>

        <VALID_COUNTRY>
            <COUNTRY>UK</COUNTRY>

            <FOUND>NOT FOUND</FOUND>
        </VALID_COUNTRY>

        <VALID_COUNTRY>
            <COUNTRY>AU</COUNTRY>

            <FOUND>NOT FOUND</FOUND>
        </VALID_COUNTRY>        

    </COUNTRIES>
    <SomeOtherData/>
    <DATA>
        <FURTHER>
            <CountryInfo>
                <Country>DK</Country>
            </CountryInfo>
            <CountryInfo>
                <Country>US</Country>
            </CountryInfo>
            <CountryInfo>
                <Country>UK</Country>
            </CountryInfo>
            <CountryInfo>
                <Country>AU</Country>
            </CountryInfo>
        </FURTHER>
    </DATA>
</Root>

попытались использовать групповой режим xslt (для 2.0) и функцию ключа вместе с генерацией идентификатора, но не получая правильный вывод. Я могу использовать xslt 3.0 для этого.

Вот код, который я пробовал,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hci="http://sap.com/it/" exclude-result-prefixes="hci">
    <xsl:output method="xml" indent="yes"/>
    <!-- Identity template : copy all text nodes, elements and attributes -->
    <xsl:key name="CountryKey" match="//FURTHER/CountryInfo" use="Country"/>
    <xsl:variable name="tempCountry" select="./COUNTRY"/>
    <xsl:template match="/*">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="VALID_COUNTRY">
        <xsl:for-each select="//VALID_COUNTRY[generate-id()=generate-id(key('CountryKey', ./COUNTRY)[1])]">
            <VALID_COUNTRY>     <xsl:value-of select="./COUNTRY"></xsl:value-of>        </VALID_COUNTRY>
            <LANGUAGE><xsl:value-of select="./LANGUAGE"></xsl:value-of></LANGUAGE>

        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

1 Ответ

1 голос
/ 11 февраля 2020

Как вы говорите, вы можете использовать XSLT 2 или 3, вы можете использовать for-each-group в любом случае или xsl:merge с XSLT 3; группировка будет

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:mode name="add" on-no-match="shallow-copy"/>

  <xsl:template match="COUNTRIES">
      <xsl:copy>
          <xsl:for-each-group select="VALID_COUNTRY, /Root/DATA/FURTHER/CountryInfo" group-by="COUNTRY, Country">
              <xsl:apply-templates select="." mode="add"/>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="VALID_COUNTRY/LANGUAGE" mode="add">
      <xsl:copy-of select="."/>
      <FOUND>
          <xsl:value-of select="if (current-group()[2]) then 'YES' else 'NEW COUNTRY'"/>
      </FOUND>
  </xsl:template>

  <xsl:template match="CountryInfo" mode="add">
      <VALID_COUNTRY>
          <COUNTRY>
              <xsl:value-of select="Country"/>
          </COUNTRY>
          <FOUND>NOT FOUND</FOUND>
      </VALID_COUNTRY>
  </xsl:template>

https://xsltfiddle.liberty-development.net/ejivJse

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...