由于换行导致的 DTD 字符数据验证错误
DTD character data validation error due to linebreak
我有以下 fake.dtd
文件:
<!ELEMENT outer - - (#PCDATA, foo, bar) >
<!ELEMENT foo - o (#PCDATA) >
<!ELEMENT bar - - (#PCDATA) >
以及以下 SGML 文档:
<!DOCTYPE outer SYSTEM "fake.dtd">
<OUTER>Document Title
<FOO>1234
<BAR>wxyz</BAR>
</OUTER>
我在使用 nsgmls
:
时收到验证错误
4:19:E: character data is not allowed here
注意把</OUTER>
和</BAR>
放在同一行就解决了问题;错误是指换行符。
有没有办法让 SGML 保持原样(因为我已经有数千个这样的文档),但更改 DTD 以使其有效?
在 outer
元素的末尾添加另一个 #PCDATA
似乎很愚蠢,因为这会使换行符以外的字符合法。
看似无害的空格实际上是重要的字符数据,这会导致错误。这有时称为 "pernicious mixed content"。您已经暗示了一个解决方案(允许 #PCDATA
在 bar
元素之后):
<!ELEMENT outer - - (#PCDATA, foo, bar, #PCDATA) >
另一种选择是允许 #PCDATA
和任何顺序的元素(这是必须在 XML 中声明混合内容的方式):
<!ELEMENT outer - - (#PCDATA|foo|bar)* >
我想不出别的了。无法将 #PCDATA
内容限制为仅某些字符。
SGML 标准 (ISO 8879:1986/A1:1988, 11.2.4) 明确建议不要使用 内容模型,如 (#PCDATA, foo, bar)
(强调我的):
NOTE - It is recommended that “#PCDATA
” be used only when data characters are to be permitted anywhere in the content of the element; that is, in a content model where it is the sole token, or where or
is the only connector used in any model group.
尽管提及 #PCDATA
仅作为组中的第一个标记,您的 outer
元素类型仍被声明为具有 混合内容 ,因此数据字符可以出现在任何地方:这就是为什么 </BAR>
之后的换行符(又名 "record end")被识别为 数据字符 一方面不仅仅是 分隔符 ,但另一方面没有相应的 #PCDATA
标记来吸收它,因此出现错误。 (只有省略的 </FOO>
结束标记避免了之前行中的相同错误!)
在这种情况下,正确且常见的方法是将 "Document Title" 放入实际的 title
元素中——为此可以允许省略 both 开始和结束标签:
<!ELEMENT outer - - (title, foo, bar) >
<!ELEMENT title o o (#PCDATA) >
现在
- 您的文档实例未经修改即有效,
outer
内容模型仍然反映了元素的正确顺序,
outer
元素有元素内容(不再混合内容),
- 并且 "Document Title" 文本最终出现在它自己的
title
元素中,这是应该的。
(在多个标准 DTD 中使用了相同的技术,例如标准附件 E 中的 "General Document" 示例。)
我有以下 fake.dtd
文件:
<!ELEMENT outer - - (#PCDATA, foo, bar) >
<!ELEMENT foo - o (#PCDATA) >
<!ELEMENT bar - - (#PCDATA) >
以及以下 SGML 文档:
<!DOCTYPE outer SYSTEM "fake.dtd">
<OUTER>Document Title
<FOO>1234
<BAR>wxyz</BAR>
</OUTER>
我在使用 nsgmls
:
4:19:E: character data is not allowed here
注意把</OUTER>
和</BAR>
放在同一行就解决了问题;错误是指换行符。
有没有办法让 SGML 保持原样(因为我已经有数千个这样的文档),但更改 DTD 以使其有效?
在 outer
元素的末尾添加另一个 #PCDATA
似乎很愚蠢,因为这会使换行符以外的字符合法。
看似无害的空格实际上是重要的字符数据,这会导致错误。这有时称为 "pernicious mixed content"。您已经暗示了一个解决方案(允许 #PCDATA
在 bar
元素之后):
<!ELEMENT outer - - (#PCDATA, foo, bar, #PCDATA) >
另一种选择是允许 #PCDATA
和任何顺序的元素(这是必须在 XML 中声明混合内容的方式):
<!ELEMENT outer - - (#PCDATA|foo|bar)* >
我想不出别的了。无法将 #PCDATA
内容限制为仅某些字符。
SGML 标准 (ISO 8879:1986/A1:1988, 11.2.4) 明确建议不要使用 内容模型,如 (#PCDATA, foo, bar)
(强调我的):
NOTE - It is recommended that “
#PCDATA
” be used only when data characters are to be permitted anywhere in the content of the element; that is, in a content model where it is the sole token, or whereor
is the only connector used in any model group.
尽管提及 #PCDATA
仅作为组中的第一个标记,您的 outer
元素类型仍被声明为具有 混合内容 ,因此数据字符可以出现在任何地方:这就是为什么 </BAR>
之后的换行符(又名 "record end")被识别为 数据字符 一方面不仅仅是 分隔符 ,但另一方面没有相应的 #PCDATA
标记来吸收它,因此出现错误。 (只有省略的 </FOO>
结束标记避免了之前行中的相同错误!)
在这种情况下,正确且常见的方法是将 "Document Title" 放入实际的 title
元素中——为此可以允许省略 both 开始和结束标签:
<!ELEMENT outer - - (title, foo, bar) >
<!ELEMENT title o o (#PCDATA) >
现在
- 您的文档实例未经修改即有效,
outer
内容模型仍然反映了元素的正确顺序,outer
元素有元素内容(不再混合内容),- 并且 "Document Title" 文本最终出现在它自己的
title
元素中,这是应该的。
(在多个标准 DTD 中使用了相同的技术,例如标准附件 E 中的 "General Document" 示例。)