6

DTD を使用して XML ドキュメント (イーグル ファイル) を読み取ろうとすると、次のエラーが表示されます。

プロジェクト xx で例外クラス EDOMParserError が発生し、「DTD は禁止されています」というメッセージが表示されました

XML ヘッダーは次のようになります。

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

2行目を外すと…

<!DOCTYPE eagle SYSTEM "eagle.dtd">

...すべて正常に動作します。

グーグル検索の結果、MSXML パーサーには「prohibitDTD」というオプションがデフォルトでtrueに設定されているようです (以前のバージョンでは false でした)。

ただし、TXMLDocument クラスからこのオプションを false に設定することはできないようです。解決策の 1 つは、.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;

ありがとうございました...

4

3 に答える 3

5

XE2 は、まさにこの問題に対するネイティブ ソリューションを導入しました。宣言されたboolという名前のグローバル変数があります。にデータをロードする前に、次のように設定できます。MSXML6_ProhibitDTDXml.Win.msxmldom.hppfalseTXMLDocument

#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;
于 2012-05-28T01:03:45.217 に答える
1

グローバル変数を使用した回避策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です。背後にある概念がわかりません。)

Delphi ブログから着想を得た: https://bobsotherblog.wordpress.com/2013/09/19/fixing-dtd-is-prohibited-error-in-delphi/

于 2015-04-24T07:22:24.903 に答える
0

この問題を解決するには、MSXMLDOM.pas をプロジェクト フォルダーにコピーし、変更する必要があります。

の実装をfunction TMSDOMDocument.GetMSDocument次のように変更し、プロジェクトを再構築します。

公開しないため、直接IXMLDOMDocument2.setPropertyアクセスする代わりに使用する必要があることに注意してください。ProhibitDTDIXMLDOMDocument2ProhibitDTD

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 フォーラムの検索機能はこれまでうまく機能していませんでした。:-)

于 2012-05-27T03:52:22.263 に答える