C++ Builder XE2, TXMLDocument 'DTD запрещен'

когда я пытаюсь прочитать XML-документ (файл eagle) с DTD, я получаю ошибку:

проект xx вызвал класс исключения EDOMParserError с сообщением " DTD запрещено'

заголовок XML выглядит следующим образом:

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

Если я удалю вторую строку...

<!DOCTYPE eagle SYSTEM "eagle.dtd">

...все работает нормально.

после некоторого googling кажется, что парсер MSXML имеет параметр prohibitDTD, установленный в правда по умолчанию (в более ранних версиях это было false).

однако кажется невозможным установить этот параметр в false из класса TXMLDocument. Одним из решений представляется перекомпиляция .библиотека pas или создать интерфейс самостоятельно с помощью CoCreateInstance ().

все примеры, которые я видел, есть в Delphi, и у меня возникли трудности с трас-нлате их в C++ Builder.

кто-нибудь знает, как читать DTD XML-документ с C++ Строитель XE2 в?

мой пример кода...

#include <xmldoc.hpp>

_di_IXMLNode XMLObject;

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

спасибо...

3 ответов


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 экземпляры динамически, как это. Лучше использовать вместо:

#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 сам по себе наследуется от интерфейса metaclass или около того. У меня нет концепции.)

вдохновленный блогом delphi: https://bobsotherblog.wordpress.com/2013/09/19/fixing-dtd-is-prohibited-error-in-delphi/


вам нужно скопировать MSXMLDOM.вставьте в папку проекта и измените ее, чтобы устранить эту проблему.

изменить реализацию 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;

обратите внимание, что это будет работать только если вы не дом с пакетами времени выполнения!

это решение из сообщение Embarcadero forums, сделанное членом TeamB; я вспомнил, что читал его, и нашел его в поиске этих форумов через CodeNewsFast - функциональность поиска на форумах EMBT никогда не работала хорошо, а недавняя перестройка или переиндекс или что-то еще сделали ее еще хуже, чем раньше. :-)