倭マン's BLOG

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

単純化(19) : , 要素

単純化の第19段階は、<define>, <ref> 要素の処理です。

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

到達不可能な <define> 要素の除去

対象ノード
//rng:define
操作
到達可能*1でないなら除去する。

サンプル

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

  <define name="DEFINE1">
    <ref name="DEFINE2">
  </define>

  <define name="DEFINE2">
    <element>
      <name ns="">ELEMENT</name>
      <empty/>
    </element>
  </define>

  <define name="DEFINE2">
    <attribute>
      <name ns="">ATTRIBUTE</attribute>
      <text/>
    </attribute>
  </define>
</grammar>

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

  <define name="DEFINE1">
    <ref name="DEFINE2">
  </define>

  <define name="DEFINE2">
    <element>
      <name ns="">ELEMENT</name>
      <empty/>
    </element>
  </define>
</grammar>

<define> 要素の子要素でない <element> 要素の処理

対象ノード
//rng:element[not(../rng:define)]
操作
トップレベルの &grammar> 要素に新に <define> 要素を付け加え、その子要素として対象の <element> 要素とその子孫要素を付け加える。 <element> 要素が元あった位置には、新に付け加えた <define> 要素を参照する <ref> 要素を付け加える。

サンプル

<grammar>
  <define name="DEFINE">
    <element>
      <name ns="">ELEMENT1</name>
      <element>
        <name ns="">ELEMENT2</name>
        <empty/>
      </element>
    </element>
  </define>
</grammar>

<grammar>
  <define name="DEFINE">
    <element>
      <name ns="">ELEMENT1</name>
      <ref name="DEFINE1">
    </element>
  </define>

  <define name="DEFINE1">
    <element>
      <name ns="">ELEMENT2</name>
      <empty/>
    </element>
  </define>
</grammar>

注意

  • トップレベル <grammar> 要素に新に付け加える <define> 要素の名前(@name 属性)は、既にある <define> 要素の名前とは異なるものにしなければなりません。

<ref> 要素の展開

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

サンプル

<grammar>
  <define name="DEFINE1">
    <element>
      <name ns="">ELEMENT</name>
      <ref name="DEFINE2"/>
    </element>
  </define>

  <define name="DEFINE2">
    <choice>
      <empty/>
      <text/>
    </choice>
  </define>
</grammar>

<grammar>
  <define name="DEFINE1">
    <element>
      <name ns="">ELEMENT</name>
      <choice>
        <empty/>
        <text/>
      </choice>
    </element>
  </define>
</grammar>

子要素が <element> 要素でない <define> 要素の除去

対象ノード
//rng:define[not(rng:element)]
操作
除去する

サンプル

サンプルは略。

事後条件

  • すべての <element> 要素が <define> 要素の子要素になっている。
  • すべての <define> 要素の子要素が <element> 要素になっている。

*1:<define> 要素が到達可能」とは、その <define> 要素を参照している到達可能な <ref> 要素が存在することです。 「<ref> 要素が到達可能」とは、それが <start> 要素もしくは到達可能な <define> 要素の子孫要素であることです。