0

私の XSLT サガのこの章は、質問hereの延長です。ここまで助けてくれた皆さん (@Martin Honnen、@Ian Roberts、@Tim C、その他私が見逃した人) に感謝します!

これが私の現在の問題です:

  1. のいくつかの兄弟を並べ替えて、A_v1.xmlを作成しますA_v2.xmlこれら 2 つのファイルは、同じファイルの異なる「バージョン」であると考えています。 ファイル 2 つのファイルの内容はまったく同じですが、兄弟の順序が異なるだけです。別の言い方をすれば、 の各要素A_v2.xmlは の場合と同じ親を持っていA_v1.xmlますが、以前は後に発生していた兄弟の前に発生するか、前に発生していた兄弟の後に発生する可能性があります。
  2. 私は変身A_v1.xmlするA_v1_transformed.xml
  3. 私は変身A_v2.xmlするA_v2_transformed.xml
  4. 私は、それらが同一ではないことに失望していますA_v1_transformed.xmlA_v2_transformed.xmlさらに、どちらも に示した予想どおりの順序ではありませんexpected.xml。内容は同じですが、要素は同じ順序でソートされていません。

私の最初の並べ替えは<xsl:sort select="local-name()"/>. @G. ケン・ホルマンは私をオンにしました<xsl:sort select="."/>(これは私が使用していたものと同じ効果が<xsl:sort select="self::*"/>あります)。これらの 2 つの並べ替えを組み合わせて使用​​すると、ほぼ正確に必要なものが得られますが、予想されるアルファベット順がランダムに壊れているように見える場所もあります。

サンプルファイルを強化しました。質問を短くするために、私はそれらをペーストビンに入れました。

A_v1.xml

A_v2.xml

A_v1_transformed.xml

A_v2_transformed.xml

これは、変換によってこれらのファイルが正しくソートされなかった場所/理由を理解できるように、私がコメントを追加した変換済みファイルの 1 つです。同様の「失敗」があるため、他の変換されたファイルについてはコメントしませんでした。

A_v1_transformed_with_comments.xml

変換されたドキュメントは両方とも と同じチェックサムを持つ必要がありますexpected.xmlが、そうではありません。 それが私の最大の関心事です。アルファベット順の並べ替えは並べ替えの最も適切な方法のようですが、変換が適切な方法で並べ替えられている限り、同じファイルの異なる「バージョン」間で並べ替えが繰り返される限り 、並べ替えがどのように行われたかはあまり気にしませんでした。

予想される.xml

次の XLS ファイルはどちらも同じ結果になりますが、「マルチパス」バージョンの方が理解しやすい場合があります。

xsl_concise.xsl

xsl_multi_pass.xsl

議論のポイント:

  1. アルファベット順に並べ替えると、大文字の文字が優先されることに気付きました。大文字がアルファベット順で小文字の後に来る場合でも、並べ替えでは最初になります。

部分的な成功...

私は自分で部分的な解決策に出くわしたかもしれないと思いますが、なぜそれが機能するのかは不明です。私のxsl_multi_pass.xslファイルを見ると、次のように表示されます。

    <!-- Third pass with sortElements mode templates -->
    <xsl:variable name="sortElementsRslt">
        <xsl:apply-templates mode="sortElements" select="$sortAttributesRslt"/>
    </xsl:variable>

    <!-- Fourth pass with deDup mode templates -->
    <xsl:apply-templates mode="deDup" select="$sortElementsRslt"/>

それを次のようにすると:

    <!-- Third pass with sortElements mode templates -->
    <xsl:variable name="sortElementsRslt1">
        <xsl:apply-templates mode="sortElements" select="$sortAttributesRslt"/>
    </xsl:variable>

    <!-- Fourth pass with sortElements mode templates -->
    <xsl:variable name="sortElementsRslt2">
        <xsl:apply-templates mode="sortElements" select="$sortElementsRslt1"/>
    </xsl:variable>

    <!-- Fifth pass with deDup mode templates -->
    <xsl:apply-templates mode="deDup" select="$sortElementsRslt2"/>

これは要素を 2 回ソートします。なぜ必要なのかわかりません。私が提供したサンプルファイルを使用した結果は、私が期待したものから優先されるCAPITALIZED文字を差し引いたものですが、結果が一貫しているように見える限り、それは私を悩ませません. 問題は、この「解決策」によって、私が作業している実際のファイルの別の部分が矛盾してソートされることです。

成功!

私は最終的にこれを100%思い通りに機能させたと思います。ここ@Dimitre Novatchevが回答した関数を、属性名と値で要素に組み込みました。何らかの理由で、上記で説明したように、要素を並べ替えるには 2 つのパスを実行する (まったく同じテンプレートを 2 回適用する) 必要がありますが、20MB のファイルでさらに 3 秒かかるだけなので、あまり心配していません。

最終結果は次のとおりです。

xsl_2.0_full_document_sorter.xsl

4

2 に答える 2

1

一言で言えば、すべての XSLT に関する質問に対する私の最終的な目標は、ファイルに適用すると、そのファイルの異なる「バージョン」で実行しても常に同じ結果が生成されるスタイルシートです。ファイルの別の「バージョン」とは、順序が異なるだけで、まったく同じ内容のファイルです。これは、要素の属性が移動された可能性があり、その要素が以前よりも早く/遅く発生した可能性があることを意味します。

この目的のために、XSLT ではなく別のツールを検討しましたか? あなたが説明した目標はsimilar()XMLUnitの定義とほぼ同じように聞こえます

// control and test are the two XML documents you want to compare, they can
// be String, Reader, org.w3c.dom.Document or org.xml.sax.InputSource
Diff d = new Diff(control, test);
assert d.similar();
于 2013-09-20T10:44:28.447 に答える