C++ Builder XE2, TXMLDocument 'DTD is prohibited'



当我尝试使用 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论坛的搜索功能从来没有很好地工作过,最近的重建或重新索引或其他事情使它比以前更糟。:-)

最新更新