【问题标题】:Using a doctype with XML使用带有 XML 的文档类型
【发布时间】:2009-04-07 22:33:48
【问题描述】:

我正在使用单独的 .dtd 文件作为我的自定义 xml 文件的 doctype:

names.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE name SYSTEM "names.dtd">
<names>
    <name>
        <text>Pep&eacute;</text>
        <creator>&lost;</creator>
        <history>&lost;</history>
    </name>
    <name>
        <text>Charles</text>
        <creator>James</creator>
        <history>&lost;</history>
    </name>
</names>

names.dtd

<!ELEMENT name (text, creator+, history)>
<!ELEMENT text (#PCDATA)>
<!ELEMENT creator (#PCDATA)>
<!ELEMENT history (#PCDATA)>

<!-- Placeholder/unknown history or creator name -->
<!ENTITY lost "Lost in the depths of time.">
<!ENTITY eacute "é">

但是,当尝试访问 names.xml 时,出现以下错误:

XML 解析错误:未定义的实体 地点: http://localhost/.../names.xml线 第 5 号,第 18 栏:

<text>Pep&eacute;</text>
---------^

为了澄清,names.xml 和 names.dtd 位于同一目录中,使用 http://localhost/.../names.dtd 也不起作用。

但是,当将 &lt;!ENTITY 放入 &lt;!DOCTYPE 中时,这似乎确实有效。有人可以就此提出建议吗?

【问题讨论】:

    标签: xml dtd doctype entities


    【解决方案1】:

    如果您在 Firefox 中打开文档以尝试确定 dtd 是否正确,请不要这样做。 Firefox 不会通过适当的 xml 解析器传递 xml 和 dtd。在 IE 中打开您的 xml 文档,这将导致您的文档通过 MSXML 解析器。

    当在 IE 中打开 xml 文档时,它会抛出一个关于你的 DTD 使用无效字符的错误。您需要使用 eacute 的字符代码而不是字符本身。这是我要工作的代码...

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE NAME SYSTEM "names.dtd">
    <names>
        <name>
            <text>Pep&eacute;</text>
            <creator>&lost;</creator>
            <history>&lost;</history>
        </name>
        <name>
            <text>Charles</text>
            <creator>James</creator>
            <history>&lost;</history>
       </name>
    </names>
    

    <!ELEMENT name (text, creator+, history)>
    <!ELEMENT text (#PCDATA)>
    <!ELEMENT creator (#PCDATA)>
    <!ELEMENT history (#PCDATA)>
    
    <!ENTITY lost "Lost in the depths of time.">
    <!ENTITY eacute "&#233;">
    

    【讨论】:

    • 如果编码OK,可以直接在外部DTD主题中使用‘é’字符。默认情况下,它应该是 UTF-8;您可以通过在 .dtd 顶部使用不同的“编码”包含“文本声明”来更改此设置。 (文本声明与 声明基本相同。)
    • 顺便说一句,XML 解析器不包含外部引用(例如 DTD 外部子集)是合法的,而且浏览器不允许在网页上使用它是一件好事,因为它可以启用跨站点脚本。在这种情况下,未声明的实体引用会发生什么是实现定义的。
    • 更正:Firefox 使用适当的 XML 解析器,但实体解析器(将系统 id 解析为字节流的东西)已被黑客入侵以将外部 DTD 解析为零长度流。
    【解决方案2】:

    Firefox does not load external DTDs(Safari 也没有;它 looks like 没有浏览器)。如果我告诉它加载外部 DTD,您的 DTD 和 XML 在 xmllint 中工作正常:

    $ xmllint --loaddtd names.xml 
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE names SYSTEM "names.dtd">
    <names>
        <name>
            <text>Pep&eacute;</text>
            <creator>&lost;</creator>
            <history>&lost;</history>
        </name>
        <name>
            <text>Charles</text>
            <creator>James</creator>
            <history>&lost;</history>
        </name>
    </names>
    

    编辑:正如 hsivonen 在 cmets 中指出的那样,使用 DTD 解析外部实体是 bad idea。通常不应在 Web 上使用 DOCTYPE 或 DTD。如果您想验证一个文档,您应该使用一个单独的架构(为此建议使用RELAX NG),而不是嵌入在文档本身中的 DTD。

    【讨论】:

    • 浏览器加载DTD是个非常糟糕的主意:hsivonen.iki.fi/no-dtd
    • 是的,你是对的。我想知道他们中的任何一个是否甚至加载了本地 DTD。不过,很好地参考了为什么 DTD 是一个坏主意。
    • @hsivonen 更新了我的答案,包括为什么 DTD 是一个坏主意的信息;谢谢你的好文章。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 2010-10-15
    • 2010-10-15
    • 1970-01-01
    相关资源
    最近更新 更多