3

HTMLに変換したいXMLがあるとします。XMLは、順序付けられたセクションに分割されています。

<?xml version="1.0" encoding="utf-8"?>
<root>
  <section attr="someCriteria">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
  </section>
  <section attr="someOtherCriteria">
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </section>
  <section attr="anotherSetOfCriteria">
    <warning>
      Warning: This product could kill you
    </warning>
  </section>
  <section attr="evenMoreCriteria">
    <disclaimer>
      You were warned
    </disclaimer>
  </section>
  <section attr="criteriaSupreme">
    <p>Copyright 1999-2011</p>
  </section>
</root>

私はこれらのXMLドキュメントをいくつか持っています。基準に基づいてこれらのセクションをグループ化して変換する必要があります。2種類のバケットがあります。

  • したがって、最初のセクションはバケットに入れられます(例<div class="FormatOne"></div>
  • 2番目のセクションが「FormatOne」バケットの資格を得る基準を満たしている場合、それもこのバケットに入れられます
  • 3番目のセクションに別のバケットが必要な場合(例<div class="FormatTwo"></div>)、新しいバケットが作成され、セクションの内容がこのバケットに配置されます
  • 4番目のセクションのバケットに「FormatOne」(以前のフォーマットとは異なる)が必要な場合は、新しいバケットが再度作成され、セクションの内容がこのバケットに配置されます。
  • など。各セクションは、同じ形式の場合、前のセクションと同じバケットに入ります。そうでない場合は、新しいバケットが作成されます。

したがって、各ドキュメントについて、バケットを分離するためのロジックによっては、ドキュメントは次のようになる可能性があります。

<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </div>
  <div class="FormatTwo">
    <span class="warningText">
      Warning: This product could kill you
    </span>
  </div>
  <div class="FormatOne">
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

これ:

<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
  </div>
  <div class="FormatTwo">
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </div>
  <div class="FormatOne">
    <span class="warningText">
      Warning: This product could kill you
    </span>
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

またはこれさえ:

<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
    <span class="warningText">
      Warning: This product could kill you
    </span>
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

セクションの定義方法によって異なります。

XSLTを使用してこのタイプのグループ化マジックを実行する方法はありますか?

どんな助けでも素晴らしいでしょう。ありがとう!

4

3 に答える 3

3

私は、各セクションを順番に打つことを含む解決策を思いつきました。各セクションの処理は、「シェル」部分と「コンテンツ」部分の2つの部分に分かれています。「シェル」は<div class="FormatOne">...</div>ビットのレンダリングを担当し、「コンテンツ」は現在のセクションとそれに続くすべてのセクションの実際のコンテンツを、一致しないセクションが見つかるまでレンダリングする責任があります。

一致しないセクションが見つかると、コントロールはそのセクションの「シェル」テンプレートに戻ります。

これにより、興味深い柔軟性が得られます。「シェル」テンプレートは、一致するものが非常に積極的であり、「コンテンツ」セクションはより識別力が高い場合があります。warning具体的には、最初の出力例では、要素をとして表示する必要があります<span class="warningText">...</span>。これは、より厳密に一致するテンプレートを使用して実現されます。

すべての「コンテンツ」テンプレートは、現在のセクションのコンテンツをレンダリングした後、「次の」適切なコンテンツセクションを探す名前付きテンプレートを呼び出します。これは、「一致する」セクションとして適格なものを決定するためのルールを統合するのに役立ちます。

ここで実際の例を見ることができます

これが私のコードで、最初の例で要求したものを複製するために構築されています。

<?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" />

    <xsl:template match="/">
        <body>
            <xsl:apply-templates select="/root/section[1]" mode="shell" />
        </body>
    </xsl:template>

    <xsl:template match="section[
        @attr = 'someCriteria' or
        @attr = 'someOtherCriteria' or
        @attr = 'evenMoreCriteria' or
        @attr = 'criteriaSupreme']" mode="shell">

        <div class="FormatOne">
            <xsl:apply-templates select="." mode="contents" />
        </div>

        <xsl:apply-templates select="following-sibling::section[
            @attr != 'someCritera' and
            @attr != 'someOtherCriteria' and
            @attr != 'evenMoreCriteria' and
            @attr != 'criteriaSupreme'][1]" mode="shell" />

    </xsl:template>

    <xsl:template name="nextFormatOne">
        <xsl:variable name="next" select="following-sibling::section[1]" />
        <xsl:if test="$next[
            @attr = 'someCriteria' or
            @attr = 'someOtherCriteria' or
            @attr = 'evenMoreCriteria' or
            @attr = 'criteriaSupreme']">
            <xsl:apply-templates select="$next" mode="contents" />
        </xsl:if>
    </xsl:template>

    <xsl:template match="section[
        @attr = 'someCriteria' or
        @attr = 'someOtherCriteria']" mode="contents">

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

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'evenMoreCriteria']" mode="contents">
        <span class="disclaimerText">
            <xsl:value-of select="disclaimer" />
        </span>

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'criteriaSupreme']" mode="contents">
        <p class="copyright">
            <xsl:value-of select="p" />
        </p>

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'anotherSetOfCriteria']" mode="shell">
        <div class="FormatTwo">
            <xsl:apply-templates select="." mode="contents" />
        </div>
        <xsl:apply-templates select="
            following-sibling::section[@attr != 'anotherSetOfCriteria'][1]"
            mode="shell" />
    </xsl:template>

    <xsl:template name="nextFormatTwo">
        <xsl:variable name="next" select="following-sibling::section[1]" />
        <xsl:if test="$next[@attr = 'anotherSetOfCriteria']">
            <xsl:apply-templates select="$next" mode="contents" />
        </xsl:if>
    </xsl:template>

    <xsl:template
        match="section[@attr = 'anotherSetOfCriteria']"
        mode="contents">

        <span class="warningText">
            <xsl:value-of select="warning" />
        </span>

        <xsl:call-template name="nextFormatTwo" />
    </xsl:template>

</xsl:stylesheet>
于 2011-06-23T01:46:45.290 に答える
1

「各セクションは、同じ形式の場合は前のセクションと同じバケットに入ります。そうでない場合は、新しいバケットが作成されます。」

あなたが説明したのは、本質的には命令によって実行されるタスクです

<xsl:for-each-group group-adjacent="....">

XSLT2.0で。これは、「基準」をバケット名に変換する関数を記述し、この関数をgroup-adjacent属性内で呼び出すことができることを前提としています。

では、XSLT 1.0を使用する必要があるという制約はどれほど難しいのでしょうか?

1.0に固執している場合は、ChrisNielsenによって提案された兄弟再帰のデザインパターンを使用する必要があります。

于 2011-06-23T09:07:13.727 に答える
0

template、、、ifをチェックしてchooseくださいfor-each

これら(および他のXSLT要素)を使用すると、条件付きの動作を行って、異なる変換ロジックを切り替えることができます。

于 2011-06-23T00:51:34.460 に答える