XML 内部サブセットと引数実体参照

整形式制約から、 XML の内部サブセットでは、 リテラル内含めて宣言中に引数実体参照を使えません。 この点は、 XML 1.0 でも 1.1 でもそこは同じなので、 1.0 の仕様から。

XML 1.0

Well-formedness constraint: PEs in Internal Subset

In the internal DTD subset, parameter-entity references MUST NOT occur within markup declarations; they may occur where markup declarations can occur.

なので、 次のように書いてしまうと整形式ではありません。 root 要素の定義中に引数実体参照を使っているためです。

xml - Parameter entities in internal DTD - Stack Overflow

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root [
  <!ENTITY % placeholder "my, element, list">
  <!ELEMENT root (%placeholder;)>
  <!ELEMENT my (#PCDATA)>
  <!ELEMENT element (#PCDATA)>
  <!ELEMENT list (#PCDATA)>
]>
<root>
  <my />
  <element />
  <list />
</root>

ところで、 上の制約のすぐ下に次の但し書きがあります。 ここには、 内部サブセットで許されている引数実体参照の置換文の解析は外部サブセットの生成規則に従うことと書いてあるわけですけど、 その際、 生成規則は外部サブセットに従っても上の整形式制約が引き続き有効なのか、 それとも外部サブセット同様にどこに引数実体参照を書いても良いのか、 明言されていません。 引数実体参照の出現可能場所は生成規則に含まれておらず、 内部サブセットへの制約が生きていると解釈することも可能なわけです。 一方で、 外部サブセットに特有の条件節を許すなら、 引数実体参照の出現可能場所も外部サブセットに合わせて良いと考えることもできます。 それに、 仕様では、 DTD による妥当性をチェックしないときは、 引数実体参照の置換文と外部サブセットの両方は無視しても良いことになっているため、 引数実体参照の置換文の扱いは外部サブセットと同じだとみなせるとも考えられます。 さらに、 引数実体の格納区画は文書実体の格納区画とは異なる区画です。 内部サブセットの解析対象は文書実体の文自体であり、 他の場所に格納してある引数実体は、 外部サブセットと同じ扱いになると考えてもおかしくはありません。

XML 1.0

Well-formedness constraint: PE Between Declarations

The replacement text of a parameter entity reference in a DeclSep MUST match the production extSubsetDecl.

つまり、 次のように内部サブセットに記述したとき、 これは整形式なのかどうかという問題です。 xmllint (1) コマンドで試すとエラーにならず、 整形式として扱っています。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root [
  <!ENTITY % placeholder "my, element, list">
  <!ENTITY % decl-root "<!ELEMENT root (&#37;placeholder;)>" >
  %decl-root;
  <!ELEMENT my (#PCDATA)>
  <!ELEMENT element (#PCDATA)>
  <!ELEMENT list (#PCDATA)>
]>
<root>
  <my />
  <element />
  <list />
</root>

ちなみに、 XML の仕様の例 (引用時に行番号削除) は、 この疑問への解になっていません。

XML 1.0

<?xml version='1.0'?>
<!DOCTYPE test [
<!ELEMENT test (#PCDATA) >
<!ENTITY % xx '&#37;zz;'>
<!ENTITY % zz '&#60;!ENTITY tricky "error-prone" >' >
%xx;
]>
<test>This sample shows a &tricky; method.</test>

この例は次のように書いたのと同じことで、 引数実体参照 xx の置換文に置き換えても、 内部サブセットに対する整形式制約に従っています。

<?xml version='1.0'?>
<!DOCTYPE test [
<!ELEMENT test (#PCDATA) >
<!ENTITY % zz '&#60;!ENTITY tricky "error-prone" >' >
%zz;
]>
<test>This sample shows a &tricky; method.</test>

次のように書いたときに、 整形式なのかそうでないのかが仕様に明記してあれば、 悩まずに済んだのでしょう。

<?xml version='1.0'?>
<!DOCTYPE test [
<!ELEMENT test (#PCDATA) >
<!ENTITY % xx '&#37;zz;'>
<!ENTITY % yy 'error-prone'>
<!ENTITY % zz '&#60;!ENTITY tricky "&#37;yy;" >' >
%zz;
]>
<test>This sample shows a &tricky; method.</test>

ちなみに、 xmllint (1) コマンドは、 これもエラーにせずに整形式として扱います。