倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

単純化(7) : <include> 要素

単純化の第7段階は、前回の <externalRef> 要素の解決に続き、外部参照要素 <include> の解決です。

  • 対象ノードの箇所では接頭辞 "rng" は「RELAX NG 名前空間」に関連づけられているとします。
  • サンプルでは見やすさのために空白や改行を入れているところがありますが、実際には単純化の第2段階で除去されています。

<include> 要素を解決する


@href 属性が参照しているスキーマ定義から <grammar> 要素を構築します。

対象ノード
//rng:include
操作
次の手順を参照
  1. @href 属性の値が URI として指しているリソースから <grammar> を構築する。
  2. <include> 要素を <div> 要素に変更し、@href 属性を除去する。
  3. 変更した <div> 要素に、最初に構築した <grammar> 要素を子要素として付加する*1
  4. 付加した <grammar> 要素を <div> 要素に変更する。

サンプル1

まずは、比較的簡単な例を。 参照対象のスキーマ定義 "referee.rng" が次のように与えられているとします:

<grammar>
  <start>
    <ref name="Referee"/>
  </start>

  <define name="Referee">
    <element name="referee"><empty/></element>
  </define>
</grammar>

このとき、以下のようなスキーマ

<element name="referer">
  <include href="referee.rng"/>
</element>

を単純化する手順は次のようになります:

<element name="referer">
  <include href="referee.rng"/>
</element>

f:id:waman:20080515152431p:image

<!-- include → div -->
<element name="referer">
  <div/>
</element>

f:id:waman:20080515152431p:image

<!-- grammar を付加 -->
<element name="referer">
  <div>
    <grammar>
      <start>
        <ref name="Referee"/>
      </start>

      <define name="Referee">
        <element name="referee"><empty/></element>
      </define>
    </grammar>
  </div>
</element>

f:id:waman:20080515152431p:image

<!-- grammar → div -->
<element name="referer">
  <div>
    <div>
      <start>
        <ref name="Referee"/>
      </start>

      <define name="Referee">
        <element name="referee"><empty/></element>
      </define>
    </div>
  </div>
</element>

サンプル2

もう少し複雑なサンプルを。 参照対象のスキーマ定義 "referee.rng" は上記のサンプルと同じとします。 一方、単純化するスキーマが次のようであったとしましょう:

<element name="referer">
  <include href="referee.rng" ns="some-uri">
    <define name="Referee">
      <element name="referee2"><text/></element>
    </define>
  </include>
</element>

先ほどと違うのは

  • <include> 要素の @ns 属性
  • <include> 要素の子要素 <define>

です*2

これを単純化する手順は次のようになります:

<element name="referer">
  <include href="referee.rng" ns="some-uri">
    <define name="Referee">
      <element name="referee2"><text/></element>
    </define>
  </include>
</element>

f:id:waman:20080515152431p:image

<!-- include → div -->
<element name="referer">
  <div ns="some-uri">
    <define name="Referee">
      <element name="referee2"><text/></element>
    </define>
  </div>
</element>

f:id:waman:20080515152431p:image

<!-- grammar を付加 -->
<element name="referer">
  <div ns="some-uri">
    <grammar>
      <start>
        <ref name="Referee"/>
      </start>
    </grammar>

    <define name="Referee">
      <element name="referee2"><text/></element>
    </define>
  </div>
</element>

f:id:waman:20080515152431p:image

<!-- grammar → div -->
<element name="referer">
  <div ns="some-uri">
    <div>
      <start>
        <ref name="Referee"/>
      </start>
    </div>

    <define name="Referee">
      <element name="referee2"><text/></element>
    </define>
  </div>
</element>

事後条件

  • <include> 要素が存在しない。

*1:ただし、<include> 要素下にある <define> 要素と同名(@name 属性の値が等しい)<define> 要素がある場合は、<grammar> 要素からそれを取り除く。 同様に、<include> 要素下に <start> 要素があれば、<grammar> 要素から <start> 要素を取り除く。

*2:<include> 要素下に <define> 要素を書く場合、参照先の <grammar> 要素が同名の <define> 要素を持っていなければいけないことに注意しましょう。