倭マン's BLOG

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

@combine 属性

<define> 要素に @combine 属性を付加することによって、同等なパターンを別個に書くことができます。

@combine 属性の基本


@combine 要素は以下のように、同名の <define> 要素に付加します。 属性値は「choice」または「interleave」を指定します:

<grammar xmlns="http://relaxng.org/ns/structure/1.0">

  <start>
    <ref name="xslt"/>
  </start>

  <define name="xslt" combine="choice">
    <element name="stylesheet">...</element>
  </define>

  <define name="xslt" combine="choice">
    <element name="transform">...</element>
  </define>

</grammar>

このスキーマ定義は以下のような、<define> 要素が1つのものと等価です:

<grammar xmlns="http://relaxng.org/ns/structure/1.0">

  <start>
    <ref name="xslt"/>
  </start>

  <define name="xslt">
    <choice>
      <element name="stylesheet">...</element>
      <element name="transform">...</element>
    </choice>
  </define>

</grammar>

幾つか注意を:

  • <define> 要素下の <choice> 要素は、@combine 要素で指定したものと同じになります。 @combine 要素に「interleave」を指定すると、<define> 要素下には <interleave> 要素が付加されます。
  • 同名の <define> 要素はいくつでも書くことができますが、@combine 要素の値は全て同じでなければなりません。 ただし、1つの <define> 要素だけ @combine 属性を省略することができます*1
  • パターンの参照の仕方(<ref> 要素の書き方)は @combine 要素のあるなしで変わりありません。

<include> 要素との併用


<include> 要素は他ファイルに定義された <define> 要素を読み込む要素でした。 これと @combine 属性を付加した <define> 要素を併用することで、既存のスキーマ定義を拡張することができます。

まず、以下のようなスキーマ定義があったとしましょう(xslt.rng):

<!-- xslt.rng -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0">

  <start>
    <ref name="xslt"/>
  </start>

  <define name="xslt">
    <element name="stylesheet">...</element>
  </define>

</grammar>

このスキーマ定義を拡張して、ルート要素が <transform> でも良いようにするには、以下のようにします:

<!-- xslt-ex.rng -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0">

  <include href="xslt.rng"/>

  <start>
    <ref name="xslt"/>
  </start>

  <define name="xslt" combine="choice">
    <element name="transform">...</element>
  </define>

</grammar>

これは前節のスキーマ定義と等価なものになります。 参照先の <define> 要素には @combine 属性がいらないことに注意しましょう。

*1:これは <include> 要素と併用する際に必要な機能です。