2

XML ファイルを読み取り、選択した要素 (およびそのすべての子要素) を削除した短い XML ファイルを生成するXSLTフィルターを作成しています。

これまでのところ、フィルターは有効で整形式の XML を出力しますが、以前は削除された要素があった場所に空白行が含まれています。形式的には削除した要素の前のテキストノードが残り、空白行が発生していると思います。この空白行を削除したいのですが、他のすべてのインデントはそのままにしておきます。これどうやってするの?

私の XSLT フィルターの簡略化されたバージョンは次のとおりです。

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8" />

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

<xsl:template match="root/maybe[remove]" />

</xsl:stylesheet>

私の入力 XML ファイルの非常に単純化されたバージョンは次のとおりです。

<?xml version="1.0" encoding="utf-8" ?>
<root>
      <maybe><keep /></maybe>
   <maybe><remove/></maybe>
</root>

はい、インデントは非標準です。削除する要素を除いて、フィルターが見つけたインデントを残したいという点を強調しようとしています。これにより、従来のdiffを使用して結果を確認できます。

私が今得た出力 ( MacOS X 10.10 でxsltprocfromを使用):libxslt

<?xml version="1.0" encoding="utf-8"?>
<root>
       <maybe><keep/></maybe>

</root>

<keep/>との間の空白行</root>は、私が排除しようとしているものです。

さて、SO の他の場所で、関連する質問XSLT: how to prevent the XSLT code from generate redundancy blank-space in output xmlXSLT の空白行の削除は、XSLT フィルターにxsl:strip-spaceを追加することを提案しています。

<xsl:strip-space elements="*"/>

試してみると、出力ファイルに空白行はなくなりましたが、元のファイルとは異なるインデントになりました。

<?xml version="1.0" encoding="utf-8"?>
<root>
  <maybe>
    <keep/>
  </maybe>
</root>

<maybe>(とが別の行に<keep/>あり</maybe>、インデントが異なることに注意してください。)

では、要素とともに空白行を削除する XSLT 要素はありますが、他のインデントと改行はそのまま残しますか?

また、私の実際のファイルはGnuCashからのもので、はるかに複雑な構造を持っています。実際の XSLT フィルターには、より複雑な一致式があります。したがって、一致式を繰り返す必要がない XSLT 要素が優先されます。

<xsl:template match='gnc-v2//gnc:account[@version="2.0.0"]/act:slots/
        slot[slot:key/text()="import-map-bayes"]/slot:value[@type="frame"]/
        slot/slot:value[@type="frame"]/slot[starts-with(slot:key/text(),
            "Assets, Business, CAD:"
    )]' />

また、関連する質問インデントを使用せずに XSLT で余分な空白行を削除すると、回答が得られませんでした。そこに洞察はありません。

XSLT 1.0 を使用しているのは、それがツールでサポートされているためです。XSLT 2.0 は、この質問に対するより良い答えを提供しますか?

更新: XSLT 1 vs 2 に言及して、一致パターンをわずかに単純化しました。

4

3 に答える 3

3

このテンプレートを追加するだけです:

  <xsl:template match="text()[following-sibling::node()[1][self::maybe[remove]]]" />

完全なスタイルシートは次のようになります。

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

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

  <xsl:template match="root/maybe[remove]" />
  <xsl:template match="text()[following-sibling::node()[1][self::maybe[remove]]]" />
</xsl:stylesheet>

注意してくださいindent="yes":これは確かに出力を台無しにする(インデントを正規化する)ため、属性を削除しました。

提供された XML ドキュメントに適用した場合:

<root>
      <maybe><keep /></maybe>
   <maybe><remove/></maybe>
</root>

必要な結果が生成されます:

<root>
      <maybe><keep/></maybe>
</root>

隣接する前のコメントや処理命令も削除したい場合は、追加するテンプレートは次のとおりです。

      <xsl:template match=
          "node()[not(self::*)][following-sibling::*[1][self::maybe[remove]]]" />
于 2016-02-21T22:57:54.260 に答える
0

この XSLT フィルターにより、目的の結果が得られます。

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8" />

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

    <xsl:template match="root/maybe[./remove]" />
    <xsl:template match="root/text()[following-sibling::maybe[1]/remove]" />

</xsl:stylesheet>

結果:

<?xml version="1.0" encoding="utf-8"?>
<root>
       <maybe><keep/></maybe>
</root>

ただし、このアプローチは、一致式が長く複雑になるにつれて、すぐに見苦しくなります。2 つのテンプレート要素には、一致パターンに多くの冗長性があります。ただし、この冗長性は仕方がありません。共通部分を変数に入れることはできません。XSLT 1.0 仕様には、「match 属性の値に VariableReference が含まれているとエラーになる」と記載されています。

きっと他の誰かがもっとうまくやれるでしょうか?

于 2016-02-15T10:49:01.377 に答える