6

当我尝试使用 DTD 读取 XML 文档(eagle 文件)时,出现错误:

项目 xx 引发异常类 EDOMParserError 并带有消息“禁止 DTD”

XML 标头如下所示:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">

如果我删除第二行...

<!DOCTYPE eagle SYSTEM "eagle.dtd">

...一切正常。

经过一番谷歌搜索后,似乎 MSXML 解析器有一个名为“prohibitDTD”的选项默认设置为true(在早期版本中为 false)。

但是,似乎无法从 TXMLDocument 类将此选项设置为 false。一种解决方案似乎是重新编译 .pas 库或使用 CoCreateInstance() 自己创建接口。

我在那里看到的所有示例都在 Delphi 中,我很难将这些示例转换为 C++ Builder。

有谁知道如何使用 C++ Builder XE2 读取 DTD XML 文档?

我的示例代码...

#include <xmldoc.hpp>

_di_IXMLNode XMLObject;

TXMLDocument *XMLDocument = new TXMLDocument(this);
XMLDocument->LoadFromFile(fileName); // <----- Exception EDOMParserError
XMLObject = XMLDocument->DocumentElement;

谢谢...

4

3 回答 3

5

XE2 为这个问题引入了一个本地解决方案:有一个名为声明的全局bool变量。您可以在将数据加载到之前将其设置为:MSXML6_ProhibitDTDXml.Win.msxmldom.hppfalseTXMLDocument

#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;
于 2012-05-28T01:03:45.217 回答
1

由于不推荐使用全局变量的解决方法,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/

于 2015-04-24T07:22:24.903 回答
0

您需要将 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 成员发布的 Embarcadero 论坛帖子;我记得读过它,并在通过CodeNewsFast搜索这些论坛时找到了它——EMBT 论坛上的搜索功能一直没有很好地工作,最近的重建或重新索引或其他事情使它比以前更糟。:-)

于 2012-05-27T03:52:22.263 回答