0

xml で重複を検索し、見つかったときにすべての重複を 1 つのノードに集約する方法があるのだろうかと思います。F.eks

<car name="one">
 <person>john</person>
 <person>Jay</person>
</car>
<car name="two">
 <person>kim</person>
 <person>chris</person>
</car>
<car name="one">
 <person>jane</person>
 <person>liz</person>
</car>

次のようにする必要があります。

<car name="one">
 <person>john</person>
 <person>Jay</person>
 <person>jane</person>
 <person>liz</person>
</car>
<car name="two">
 <person>kim</person>
 <person>chris</person>
</car>

すべてのヘルプは大歓迎です!

ブラ・キム

4

2 に答える 2

1

XSLT 1.0では、関数と関数を使用して要素をグループ化するプロセスであるMuenchian メソッドと呼ばれるものを使用する必要があります。keygenerate-id

プロセスは次のようになります。

最初に、グループ化するデータを表すキーを定義します。

<xsl:key name="car-by-name" match="car" use="@name"/>

次に、そのキーに基づいて ID を生成することにより、テンプレート マッチでそのキーを使用します。

<xsl:apply-templates select="car[generate-id() = generate-id(key('car-by-name', @name)[1])]" mode="group"/>

ノードをグループ化したので、もう一度そのキーを使用して、そのキー内のすべてのノードを取得します。

<xsl:apply-templates select="key('car-by-name', @name)"/>

それでは、この XML (整形式にするために追加されたもの) を取得して、すべてをまとめて示しますdocument

<document>
  <car name="one">
    <person>john</person>
    <person>Jay</person>
  </car>
  <car name="two">
    <person>kim</person>
    <person>chris</person>
  </car>
  <car name="one">
    <person>jane</person>
    <person>liz</person>
  </car>
</document>

そして、この XSLT を適用します

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:key name="car-by-name" match="car" use="@name"/>

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

  <xsl:template match="document">
    <xsl:copy>
      <xsl:apply-templates select="car[generate-id() = generate-id(key('car-by-name', @name)[1])]" mode="group"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="car" mode="group">
    <car name="{@name}">
      <xsl:apply-templates select="key('car-by-name', @name)"/>
    </car>
  </xsl:template>

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

</xsl:stylesheet>

この結果が得られます。

<?xml version="1.0" encoding="UTF-8"?>
<document>
  <car name="one">
    <person>john</person>
    <person>Jay</person>

    <person>jane</person>
    <person>liz</person>
  </car>
  <car name="two">
    <person>kim</person>
    <person>chris</person>
  </car>
</document>
于 2013-09-16T14:06:18.687 に答える
1

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">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/data">
        <data>
            <xsl:for-each-group select="car" group-by="@name">
                <car name="{current-grouping-key()}">
                    <xsl:for-each select="current-group()/person">
                        <person><xsl:value-of select="." /></person>
                    </xsl:for-each>
                </car>
            </xsl:for-each-group>
        </data>
    </xsl:template>
</xsl:stylesheet>

次の入力に適用した場合:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <car name="one">
        <person>john</person>
        <person>Jay</person>
    </car>
    <car name="two">
        <person>kim</person>
        <person>chris</person>
    </car>
    <car name="one">
        <person>jane</person>
        <person>liz</person>
    </car>
</data>

正しい出力が生成されます。

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <car name="one">
        <person>john</person>
        <person>Jay</person>
        <person>jane</person>
        <person>liz</person>
    </car>
    <car name="two">
        <person>kim</person>
        <person>chris</person>
    </car>
</data>
于 2013-09-16T13:33:47.757 に答える