当我尝试使用 DTD 读取 XML 文档(鹰文件)时,出现错误:
项目 xx 引发异常类 EDOMParser错误,消息为"DTD 是 禁止'
XML 标头如下所示:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
如果我删除第二行...
<!DOCTYPE eagle SYSTEM "eagle.dtd">
。一切正常。
经过一些谷歌搜索,MSXML解析器似乎有一个名为"禁止DTD"的选项默认设置为true(在早期版本中为false)。
但是,似乎无法从 TXMLDocument 类中将此选项设置为 false。一种解决方案似乎是重新编译 .pas 库或使用 CoCreateInstance() 自行创建接口。
我看到的所有例子都在德尔福,我有困难将这些转移到C++生成器。
有谁知道如何使用C++生成器XE2阅读DTD XML文档?
我的示例代码...
#include <xmldoc.hpp>
_di_IXMLNode XMLObject;
TXMLDocument *XMLDocument = new TXMLDocument(this);
XMLDocument->LoadFromFile(fileName); // <----- Exception EDOMParserError
XMLObject = XMLDocument->DocumentElement;
谢谢。。。
XE2 为这个问题引入了一个原生解决方案:在 Xml.Win.msxmldom.hpp
中声明了一个名为 MSXML6_ProhibitDTD
的全局bool
变量。 您可以在将数据加载到TXMLDocument
之前将其设置为 false
:
#include <xmldoc.hpp>
#include <msxmldom.hpp>
MSXML6_ProhibitDTD = false;
TXMLDocument *XMLDocument = new TXMLDocument(this):
XMLDocument->LoadFromFile(fileName);
_di_IXMLNode XMLObject = XMLDocument->DocumentElement;
附带说明一下:像这样动态创建TXMLDocument
实例通常不是一个好主意。最好改用IXMLDocument
接口:
#include <xmldoc.hpp>
#include <msxmldom.hpp>
MSXML6_ProhibitDTD = false;
_di_IXMLDocument XMLDocument = LoadXMLDocument(fileName);
_di_IXMLNode XMLObject = XMLDocument->DocumentElement;
由于全局变量 MSXML6_ProhibitDTD
的解决方法已弃用,我也无法让它与 XE5 一起使用,这是另一种解决方案:
如文档中所述,有此方法可以更改 DOM 属性
Xml.Win.Msxmldom.MSXMLDOMDocumentFactory.AddDOMProperty
不幸的是,使用它并不是那么简单...
包括此命名空间的标头:
#include <Xml.Win.msxmldom.hpp>
Foo::Foo()
{
//change the dom property in your constructor.
((TMSXMLDOMDocumentFactory*)Xml::Win::Msxmldom::MSXMLDOMDocumentFactory)->AddDOMProperty("ProhibitDTD", False, true);
}
并访问此方法。(强制转换是必需的,因为MSXMLDOMDocumentFactory
本身继承自元类接口左右。我不明白背后的概念。
灵感来自德尔福博客:https://bobsotherblog.wordpress.com/2013/09/19/fixing-dtd-is-prohibited-error-in-delphi/
您需要将 MSXMLDOM.pas 复制到项目文件夹中,并对其进行修改才能解决此问题。
将function TMSDOMDocument.GetMSDocument
的实现更改为以下内容,然后重新生成项目。
请注意,您必须使用 IXMLDOMDocument2.setProperty
而不是直接访问ProhibitDTD
,因为IXMLDOMDocument2
不会发布ProhibitDTD
。
function TMSDOMDocument.GetMSDocument: IXMLDOMDocument;
var
Doc2: IXMLDOMDocument2;
begin
Result := MSNode as IXMLDOMDocument;
if Supports(Result, IXMLDOMDocument2, Doc2) then
Doc2.setProperty('ProhibitDTD', False);
end;
请注意,这仅在不使用运行时包构建时才有效!
该解决方案来自 TeamB 成员发布的内河码头论坛帖子;我记得读过它,并通过CodeNewsFast搜索这些论坛时发现了它 - EMBT论坛的搜索功能从来没有很好地工作过,最近的重建或重新索引或其他事情使它比以前更糟。:-)