倭マン's BLOG

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

単純化(17) : @combine 属性

単純化の第17段階は、<define> 要素にある @combine 属性の処理です。

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

@combine 属性を持つ <define> 要素の結合


1つの <grammar> 要素下にある同名(@name 属性の値が同じ)の <define> 要素を1つの <define> 要素に結合します。 結合の際に用いる要素の名前は @combine 属性の値になります。 この値として許されているものは choiceinterleave の2つです。

対象ノード
//rng:define[@combine]
操作
@name 属性の値が同じ <define> 要素の内容を、@combine 属性の値を名前とした要素でラップする。

サンプル

<define name="pattern">
  パターン1
</define>
<define name="pattern" combine="choice">
  パターン2
</define>

<define name="pattern">
  <choice>
    パターン1
    パターン2
  </choice>
</define>

注意

  • 同名の <define> 要素が3つ以上ある場合も、同様にそれらを結合します。
  • 同名の <define> 要素は全て @combine 属性の値が等しくなければいけません。 また、1つの <define> 要素のみ、@combine 属性を省略することができます。

@combine 属性を持つ <start> 要素の結合


@combine 属性を持つ <start> 要素に対しても、上記の <define> 要素と同様の操作をします。

対象ノード
//rng:start[@combine]
操作
<start> 要素の内容を、@combine 属性の値を名前とした要素でラップする。

サンプル

<start>
  パターン1
</start>
<start combine="interleave">
  パターン2
</start>

<start>
  <interleave>
    パターン1
    パターン2
  </interleave>
</start>

事後条件

  • 1つの <grammar> 要素下に、@name 属性の値が同じ <define> 要素が2つ以上存在しない。
  • 1つの <grammar> 要素下に <start> 要素が2つ以上存在しない。