我有以下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:此处不允许使用字符数据
请注意,将</OUTER>
放在与</BAR>
相同的行上可以解决问题;错误是指换行符。
有没有办法让SGML保持原样(因为我已经拥有了数千个这样的文档),但更改DTD以便验证它?
在#PCDATA
元素的末尾添加另一个outer
似乎很愚蠢,因为这会使新行以外的字符合法化。
答案 0 :(得分:1)
SGML标准(ISO 8879:1986 / A1:1988,11.2.4)明确建议不使用内容模型,如(#PCDATA, foo, bar)
(强调我的):
注意 - 当元素内容中的任何地方允许使用数据字符时,建议“
#PCDATA
”仅使用 ;也就是说,在内容模型中,它是唯一的令牌,或者其中or
是任何模型组中使用的唯一连接器。
尽管仅将#PCDATA
视为组中的第一个标记,但您的outer
元素类型仍被声明为具有混合内容,因此数据字符可以出现在任何地方:为什么</BAR>
之后的换行符(也称为“记录结束”)被识别为数据字符而不仅仅是分隔符一方面,但另一方面没有相应的#PCDATA
令牌吸收它,因此错误。 (并且只有省略的</FOO>
结束标记在之前的行中避开了相同的错误!)
在这种情况下,正确和通用的方法是将“文档标题”放入实际的title
元素中 - 为此可以允许省略两者的开头和结尾-tag:
<!ELEMENT outer - - (title, foo, bar) >
<!ELEMENT title o o (#PCDATA) >
现在
outer
内容模型仍然反映了元素的正确顺序,outer
元素包含元素内容(不再> 混合内容),title
元素中。(在几个标准DTD中使用了相同的技术,如标准附录E中的“一般文件”示例。)
答案 1 :(得分:0)
看起来无害的空白实际上是重要的字符数据,这会导致错误。这有时被称为&#34;有害的混合内容&#34;。您已经暗示了一个解决方案(在#PCDATA
元素之后允许bar
):
<!ELEMENT outer - - (#PCDATA, foo, bar, #PCDATA) >
另一种选择是以任何顺序允许#PCDATA
和元素(这是必须在XML中声明混合内容的方式):
<!ELEMENT outer - - (#PCDATA|foo|bar)* >
我想不出别的什么。无法仅将#PCDATA
内容限制为特定字符。