Delphi - 能否将 TXMLDocument 配置为忽略不正确的 DTD 实体?

Delphi - Can TXMLDocument be configured to ignore incorrect DTD entities?

我正在使用 RAD Studio XE7 编写 Delphi 代码。在我的一个项目中,我需要解析多个 SVG 文件以在屏幕上绘制它们的内容。为此,我使用 TXMLDocument 解析器。

我的一个源 SVG 包含此 XML 数据:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="32px" height="32px"
 viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<metadata>
    <sfw  xmlns="&ns_sfw;">
        <slices></slices>
        <sliceSourceBounds  height="21.334" width="32" bottomLeftOrigin="true" y="1.833" x="-4.501"></sliceSourceBounds>
    </sfw>
</metadata>
<path fill="#29ABE2" d="M4,8h24v13.333h2.667v-16H1.334v16h2.667L4,8L4,8z M21.333,22.667c-0.256,0.536-1.527,0.967-2.667,1.181V24
h-5.333v-0.152c-1.14-0.215-2.411-0.645-2.667-1.181H-0.001V24c0,1.467,4,2.667,4,2.667h24c0,0,4-1.2,4-2.667v-1.333H21.333
L21.333,22.667z M26.667,25.333h-1.333V24h1.333V25.333z"/>
</svg>

我知道上面XML的内容不完整,格式好的SVG应该包含这个XML数据:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
    <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
    <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
    <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
    <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
    <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
    <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
    <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
    <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Calque_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="32px" height="32px"
 viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<metadata>
    <sfw  xmlns="&ns_sfw;">
        <slices></slices>
        <sliceSourceBounds  height="21.334" width="32" bottomLeftOrigin="true" y="1.833" x="-4.501"></sliceSourceBounds>
    </sfw>
</metadata>
<path fill="#29ABE2" d="M4,8h24v13.333h2.667v-16H1.334v16h2.667L4,8L4,8z M21.333,22.667c-0.256,0.536-1.527,0.967-2.667,1.181V24
h-5.333v-0.152c-1.14-0.215-2.411-0.645-2.667-1.181H-0.001V24c0,1.467,4,2.667,4,2.667h24c0,0,4-1.2,4-2.667v-1.333H21.333
L21.333,22.667z M26.667,25.333h-1.333V24h1.333V25.333z"/>
</svg>

然而,在我的例子中,DTD 实体是无关紧要的(我没有对它们做任何事情),只有 svg 标签中的部分让我感兴趣。但是,如果我尝试加载这样的 XML,TXMLDocument 解析器会引发 "Reference to undefined entity 'ns_extend'" 异常,并拒绝加载 SVG。

所以我的问题是,有没有办法通知 TXMLDocument 解析器 DTD 实体在损坏时应该简单地忽略,并强制解析器继续静默读取文档?或者唯一的方法是预处理 XML,并检测并删除此类损坏?

(注意:我想尽可能避免预处理。SVG 可能来自任何地方,其中一些可能包含小的或严重的损坏,我希望以最通用的方式处理最大值可能。开始为所有可能的特殊情况添加特殊规则是一种痛苦的方式。如果 TXMLDocument 解析器能够忽略这种错误,我会非常希望。)

使用 TXMLDocument 无法忽略 DOCTYPE,唯一的方法是编辑 xml 文件,然后使用 TXMLDocument 对其进行解析,然后手动从中删除

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
    <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
    <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
    <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
    <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
    <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
    <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
    <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
    <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>

然而,它们是一些其他 xml 完全类似于 Txmldocument 的解析器(相同的方法名称和 属性 名称,完全相似,无需重做代码) 比 TXMLDocument 快 100 倍并且使用更少的内存(Txmldocument 是你能找到的最糟糕的文件)..并且忽略 DTD :)