1

カタログツリーを説明するxmlがあります。子ノードはいくつでも持つことができます。次に例を示します。

<Catalog name="AccessoriesCatalog">
<Category Definition="AccessoriesCategory" name="1532" id="1532">
</Category>
<Category Definition="AccessoriesCategory" name="16115" id="16115">
    <ParentCategory>1532</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16116" id="16116">
    <ParentCategory>16115</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16126" id="16126">
    <ParentCategory>16115</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16131" id="16131">
    <ParentCategory>1532</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16132" id="16132">
    <ParentCategory>16131</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16136" id="16136">
    <ParentCategory>16131</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16139" id="16139">
    <ParentCategory>16131</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16144" id="16144">
    <ParentCategory>16131</ParentCategory>
</Category>
<Category Definition="AccessoriesCategory" name="16195" id="16195">
    <ParentCategory>16131</ParentCategory>
</Category>

カテゴリ名とParentCategoryで並べ替えることができる必要があります。すべての親カテゴリがxmlの最初に表示され、「リーフカテゴリ」が最後に表示されます。このサンプルでは、​​xmlはすでにソートされています。

上記のxmlは、ツリーとして表される場合、次のようになります 。1532
-16115
--16116
--16126
-16131
--16132
--16136
--16139
--16144
--16195

このように並べ替え て ほしい
1532-16115-16131
--16116
--16126
--16132
--16136
--16139
--16144
--16195

子要素のいくつかのレベルにすることができます(この場合は3レベルのツリーのみ)。すべてのレベル1要素を最初にxmlに入れ、次にすべてのレベル2要素、次にすべてのレベル3要素などを配置します。

4

2 に答える 2

2

この変換:

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

 <xsl:key name="kElemById" match="Category"
  use="@id"/>

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

 <xsl:template match="/*">
  <xsl:copy>
   <xsl:copy-of select="@*"/>

   <xsl:call-template name="sortHier">
    <xsl:with-param name="pNodes" select=
    "*[ParentCategory]"/>
    <xsl:with-param name="pParents" select=
    "*[not(ParentCategory)]"/>
   </xsl:call-template>
  </xsl:copy>
 </xsl:template>

 <xsl:template name="sortHier">
  <xsl:param name="pNodes"/>
  <xsl:param name="pParents"/>

  <xsl:apply-templates select=
   "$pParents|$pNodes[not($pParents)]">
   <xsl:sort select="@name"/>
  </xsl:apply-templates>

   <xsl:if test="$pNodes and $pParents">
    <xsl:variable name="vNewParents"
     select="key('kElemById', $pNodes/ParentCategory)
                [not(@id=$pParents/@id)]
     "/>

    <xsl:variable name="vNewChildren"
     select="$pNodes[not(@id=$vNewParents/@id)]"/>

    <xsl:call-template name="sortHier">
     <xsl:with-param name="pNodes"
          select="$vNewChildren"/>
     <xsl:with-param name="pParents"
          select="$vNewParents"/>
    </xsl:call-template>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

この XML ドキュメントに適用した場合(提供されたものに基づいていますが、シャッフル/ソートされていません):

<Catalog name="AccessoriesCatalog">
    <Category Definition="AccessoriesCategory"
    name="16144" id="16144">
        <ParentCategory>16131</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16116" id="16116">
        <ParentCategory>16115</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16126" id="16126">
        <ParentCategory>16115</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16131" id="16131">
        <ParentCategory>1532</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16132" id="16132">
        <ParentCategory>16131</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16136" id="16136">
        <ParentCategory>16131</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16139" id="16139">
        <ParentCategory>16131</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="16115" id="16115">
        <ParentCategory>1532</ParentCategory>
    </Category>
    <Category Definition="AccessoriesCategory"
    name="1532" id="1532"></Category>
    <Category Definition="AccessoriesCategory"
    name="16195" id="16195">
        <ParentCategory>16131</ParentCategory>
    </Category>
</Catalog>

必要な正しい結果が生成されます

<Catalog name="AccessoriesCatalog">
   <Category Definition="AccessoriesCategory" name="1532" id="1532"/>
   <Category Definition="AccessoriesCategory" name="16115" id="16115">
      <ParentCategory>1532</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16131" id="16131">
      <ParentCategory>1532</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16116" id="16116">
      <ParentCategory>16115</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16126" id="16126">
      <ParentCategory>16115</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16132" id="16132">
      <ParentCategory>16131</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16136" id="16136">
      <ParentCategory>16131</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16139" id="16139">
      <ParentCategory>16131</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16144" id="16144">
      <ParentCategory>16131</ParentCategory>
   </Category>
   <Category Definition="AccessoriesCategory" name="16195" id="16195">
      <ParentCategory>16131</ParentCategory>
   </Category>
</Catalog>

説明:

  1. 「現在の親のセット」(または「最後に見つかった親」) と現在の (まだ処理されていない) ノードのセットの 2 つのパラメーターを使用して、名前付きテンプレートを再帰的に呼び出します。

  2. 停止条件: 「現在の親のセット」または「現在のノードのセット」のいずれか、または両方が空です。ここで@name、残りの空でないパラメータ セットを出力 (およびソート) します。

  3. 再帰的ステップ: 「現在の親」の直接の子が新しい「現在の親」になります。残りの「現在のノード」は新しい「現在のノード」になります。すべての現在の親をコピーするか、現在の親が残っていない場合はすべての現在のノードをコピーします。

更新

コメントでは、OP は、ソリューションが小さなファイルで機能していると主張してきましたが、

「しかし、より多くの要素とより多くのレベルを含む xml 全体で試してみると、機能しません。私が持っている xml は約 8Mb であるため、ここに投稿することはできません。」

私は彼に XML ファイルを (オフラインで) 提供するように依頼し、それらを入手したとき、提供された小さいファイルと大きいファイル (44000 行、700KB) の両方でこのソリューションが問題なく動作することを確認しました。

MSXML3 を除いて、より大きなファイルでのパフォーマンスはそれほど悪くはありませんでした。

以下は、私の 8 年前の (2GB RAM、3GHz シングルコア) PC で見た、44000 行のファイルのパフォーマンス データです。

MSXML3:                 91 sec.

MSXML6:                  6 sec.

AltovaXML (XMLSpy):      6 sec.

Saxon 6.5.4:             2 sec.

Saxon 9.1.05:            1.6 sec.

XslCompiledTransform     1.3 sec.

XQSharp:                 0.8 sec.
于 2011-04-22T04:02:06.863 に答える
0

あなたの答えはここにあると思います:http://www.programmersheaven.com/2/FAQ-XML-Sort-XML-By-Multiple-Attributes-XSLT

于 2011-04-21T19:37:15.353 に答える