由于换行导致的DTD字符数据验证错误

时间:2016-10-20 18:17:37

标签: dtd sgml

我有以下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似乎很愚蠢,因为这会使新行以外的字符合法化。

2 个答案:

答案 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内容限制为特定字符。