C ++ Builder XE2, TXMLDocument 'DTD not allowed'

When I try to read an XML document (eagle file) with a DTD, I get an error:

Project xx raised EDOMParserError exception class with message 'DTD is denied

The XML header is as follows:

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

If I delete the second line ...

 <!DOCTYPE eagle SYSTEM "eagle.dtd"> 

... everything is working fine.

After some Google search, it seems that by default the MSXML parser has an option called 'prohibitDTD' equal to true (in earlier versions it was false).

However, it is not possible to set this option to false from the TXMLDocument class. One solution is to recompile the .pas library or create an interface yourself using CoCreateInstance ().

All the examples I saw there are in Delphi, and I have difficulties to pass them to C ++ Builder.

Does anyone know how to read a DTD XML document using C ++ Builder XE2?

My sample code ...

 #include <xmldoc.hpp> _di_IXMLNode XMLObject; TXMLDocument *XMLDocument = new TXMLDocument(this); XMLDocument->LoadFromFile(fileName); // <----- Exception EDOMParserError XMLObject = XMLDocument->DocumentElement; 

Thanks...

+6
source share
3 answers

XE2 introduced its own solution to this very problem: there is a global bool variable named MSXML6_ProhibitDTD , declared in Xml.Win.msxmldom.hpp . You can set it to false before loading data into a TXMLDocument :

 #include <xmldoc.hpp> #include <msxmldom.hpp> MSXML6_ProhibitDTD = false; TXMLDocument *XMLDocument = new TXMLDocument(this): XMLDocument->LoadFromFile(fileName); _di_IXMLNode XMLObject = XMLDocument->DocumentElement; 

On the side of the note: it is generally not recommended to dynamically create instances of TXMLDocument . Instead, it’s better to use the IXMLDocument interface:

 #include <xmldoc.hpp> #include <msxmldom.hpp> MSXML6_ProhibitDTD = false; _di_IXMLDocument XMLDocument = LoadXMLDocument(fileName); _di_IXMLNode XMLObject = XMLDocument->DocumentElement; 
+5
source

Since the workaround with the global variable MSXML6_ProhibitDTD deprecated and I could not get it to work with XE5, here is another solution:

As stated in the documentation , this method allows you to change the DOM property

 Xml.Win.Msxmldom.MSXMLDOMDocumentFactory.AddDOMProperty 

Unfortunately, it is not so easy to use this ...

include a header for this namespace:

 #include <Xml.Win.msxmldom.hpp> Foo::Foo() { //change the dom property in your constructor. ((TMSXMLDOMDocumentFactory*)Xml::Win::Msxmldom::MSXMLDOMDocumentFactory)->AddDOMProperty("ProhibitDTD", False, true); } 

and access this method. (The cast is necessary because MSXMLDOMDocumentFactory itself MSXMLDOMDocumentFactory inherited from the metaclass interface or so. I have no concept.)

inspired by the delphi blog: https://bobsotherblog.wordpress.com/2013/09/19/fixing-dtd-is-prohibited-error-in-delphi/

+1
source

You need to copy MSXMLDOM.pas to the project folder and modify it to fix this problem.

Change the implementation of the function TMSDOMDocument.GetMSDocument to the following, and then rebuild the project.

Note that you should use IXMLDOMDocument2.setProperty instead of directly accessing ProhibitDTD , since IXMLDOMDocument2 does not publish ProhibitDTD .

 function TMSDOMDocument.GetMSDocument: IXMLDOMDocument; var Doc2: IXMLDOMDocument2; begin Result := MSNode as IXMLDOMDocument; if Supports(Result, IXMLDOMDocument2, Doc2) then Doc2.setProperty('ProhibitDTD', False); end; 

Please note that this will only work if you do not create runtime packages!

This decision is from an Embarcadero forum post made by a TeamB member; I remembered reading it and found it in the search for these forums through CodeNewsFast - the search functionality on the EMBT forums never worked, and the recent rebuild or reindexing or something made it even worse than before. :-)

0
source

Source: https://habr.com/ru/post/916769/


All Articles