1

このようなXMLファイルがあります

<fruits>
  <fruit>
    <name>banana</name>
    <country>Morocco</country>
  </fruit>
  <fruit>
    <name>orange</name>
    <country>Morocco</country>
  </fruit>
  <fruit>
    <name>grape</name>
    <country>Egypt</country>
  </fruit>
 </fruits>

そして、別の方法でグループ化する必要があります。

<fruits>
  <country name="Morocco">
    <fruit>
      <name>banana</name>
    </fruit>
    <fruit>
      <name>orange</name>
    </fruit>
  </country>
  <country name="Egypt">
    <fruit>
      <name>grape</name>
    </fruit>
  </country>
</fruits>

XSLT 2.0 から作成しようとしましfor-each-groupたが、まったくうまくいきませんでした。ネストされたパラメーターによるグループ化の処理方法がわからないため、.xsl ファイルがうまく機能しません。

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:for-each-group select="fruits/fruit" group-by="fruits/fruit/country">
    <country name="{country}">
      <xsl:for-each select="current-group()">
        <fruit>
          <name> '{name}'/</name>
        </fruit>
      </xsl:for-each>
    </country>
  </xsl:for-each-group>

</xsl:stylesheet>    
4

2 に答える 2

1

XSLT 1.0 に制限されている場合は、それを行う方法がいくつかあります。これ<fruit>は、前に同じ国の兄弟を持たないすべての要素を探します。次に、要素をコピーし、その後にそれ自体<country>の新しい<fruit>ノードと、同じ国の兄弟をそれぞれコピーします。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output indent="yes"/>

  <xsl:template match="/fruits">
    <xsl:copy>
      <xsl:apply-templates select="*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="fruit">
    <xsl:if test="not(country = preceding-sibling::fruit/country)">
      <country>
        <xsl:attribute name="name">
          <xsl:value-of select="country"/>
        </xsl:attribute>
        <xsl:for-each select="../fruit[country=current()/country]">
          <fruit>
            <xsl:copy-of select="name" />
          </fruit>
        </xsl:for-each>
      </country>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

出力

<?xml version="1.0" encoding="utf-8"?>
<fruits>
   <country name="Morocco">
      <fruit>
         <name>banana</name>
      </fruit>
      <fruit>
         <name>orange</name>
      </fruit>
   </country>
   <country name="Egypt">
      <fruit>
         <name>grape</name>
      </fruit>
   </country>
</fruits>

Muenchian メソッドは、XSLTの機能を使用することでこのクエリを高速化しkey、かなり大きなデータ セットに役立ちます。この代替ソリューションでは、要素に同じ値を持つfruit-by-countryすべての要素を、たとえば を使用して選択できるように、キーを宣言します。テンプレートは、キーを使用して、現在のが のこの値を持つ最初のものであるかどうかを確認し、同じグループ内のすべての果物を選択して一緒に表示できるようにします。出力は、前の変換の出力と同じです。<fruit><country>key('fruit-by-country', 'Morocco')<fruit><country>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output indent="yes"/>

  <xsl:key name="fruit-by-country" match="fruit" use="country" />

  <xsl:template match="/fruits">
    <xsl:copy>
      <xsl:apply-templates select="*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="fruit">
    <xsl:if test="generate-id() = generate-id(key('fruit-by-country', country)[1])">
      <country>
        <xsl:attribute name="name">
          <xsl:value-of select="country"/>
        </xsl:attribute>
        <xsl:for-each select="key('fruit-by-country', country)">
          <fruit>
            <xsl:copy-of select="name" />
          </fruit>
        </xsl:for-each>
      </country>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
于 2013-04-04T20:09:13.603 に答える
1

これはどう:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:for-each-group select="fruit" group-by="country">
        <country name="{country}">
          <xsl:for-each select="current-group()">
            <fruit>
              <name>
                <xsl:value-of select="name" />
              </name>
            </fruit>
          </xsl:for-each>
        </country>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

またはややクリーンなアプローチ:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:for-each-group select="fruit" group-by="country">
        <country name="{country}">
          <xsl:apply-templates select="current-group()" />
        </country>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="fruit/country" />

</xsl:stylesheet>

サンプル入力で実行すると、どちらも次のようになります。

<fruits>
   <country name="Morocco">
      <fruit>
         <name>banana</name>
      </fruit>
      <fruit>
         <name>orange</name>
      </fruit>
   </country>
   <country name="Egypt">
      <fruit>
         <name>grape</name>
      </fruit>
   </country>
</fruits>
于 2013-04-04T19:59:25.843 に答える