禁止使用C ++ Builder XE2,TXMLDocument' DTD'

时间:2012-05-27 01:30:56

标签: vcl c++builder-xe2 xml-dtd txmldocument

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

  

Project xx引发异常类EDOMParserError,消息'DTD is   禁止“

XML标头如下所示:

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

如果我删除第二行......

<!DOCTYPE eagle SYSTEM "eagle.dtd">

......一切正常。

在一些谷歌搜索之后,似乎默认情况下MSXML解析器有一个名为'prohibitDTD'的选项设置为 true (在早期版本中它是假的)。

但是,似乎无法从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;

谢谢...

3 个答案:

答案 0 :(得分:5)

XE2为这个问题引入了一个原生解决方案:在bool中声明了一个名为MSXML6_ProhibitDTD的全局Xml.Win.msxmldom.hpp变量。在将数据加载到false之前,您可以将其设置为TXMLDocument

#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;

答案 1 :(得分:1)

由于全局变量top: Unknown instance: 的变通方法已被弃用,我也无法使用XE5,这是另一种解决方案:

documentation中所述,有一种方法可以更改DOM属性

MSXML6_ProhibitDTD

不幸的是,使用它并不是那么简单......

包含此命名空间的标题:

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); } 本身是从元类接口继承的。我没有后面的概念。)

受到delphi博客的启发:https://bobsotherblog.wordpress.com/2013/09/19/fixing-dtd-is-prohibited-error-in-delphi/

答案 2 :(得分: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论坛上的搜索功能一直运作良好,最近的重建或重新索引或其他东西使它甚至比之前。 : - )