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 никогда не работала хорошо, а недавняя перестройка или переиндекс или что-то еще сделали ее еще хуже, чем раньше. :-)