Microsoft KB Archive/235344

= FIX: DTDs and Schemas Not Resolved When Using loadXML Method =

Article ID: 235344

Article Last Modified on 10/16/2002

-

APPLIES TO


 * Microsoft Internet Explorer 5.0
 * Microsoft XML Parser 2.0

-



This article was previously published under Q235344



SYMPTOMS
When you use the IXMLDOMDocument::loadXML method to load XML data into the MSXML parser via a string parameter, the MSXML parser does not correctly resolve any external files such as DTDs or Schemas.

Script in a Web page will not suffer from this bug because MSHTML, Internet Explorer's HTML engine, provides a valid security site object to the MSXML parser.



CAUSE
Due to a security constraint, resolveExternals is turned off while parsing the XML data loaded with loadXML.



RESOLUTION
The easiest workaround might be to call IXMLDOMDocument::load with a URL referencing an XML file. If loading from memory is preferred, there are three alternatives that will load XML Documents from memory sources and correctly resolve all external files:
 * Attach a fake site object to the MSXML engine using the IObjectWithSite::SetSite method. See the C++ or Visual Basic examples in MORE INFORMATION below.
 * Create a custom IStream wrapper over an in-memory buffer and pass it to MSXML's IPersistStream::Load or IXMLDOMDocument::load(VARIANT(IStream*)) methods. This is the most efficient mechanism for loading MSXML.
 * Create an IStream over an HGLOBAL buffer using the CreateStreamOnHGlobal API and pass it to IPersistStream::Load or IXMLDOMDocument::load(VARIANT(IStream*)). This is less efficient than loadXML or the above technique, but is easier to code.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This problem was corrected in MSXML 2.5.



MORE INFORMATION
Following are two sections of example code that create a fake site object and attach it to an XML Document.

C++ Example
Code using this alternative should call the XMLDummySecurity method and pass the IXMLDOMDocument pointer before using it to load the XML document with loadXML. class DummySite : public IUnknown { public: DummySite : _ulRefCount(1) {}

public: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject) {       if (!ppvObject) return E_POINTER;

if (riid == IID_IUnknown) {           this->AddRef; *ppvObject = (IUnknown*)this; }       else {           *ppvObject = NULL; return E_NOINTERFACE; }

return S_OK; }

virtual ULONG STDMETHODCALLTYPE AddRef( void) {       return ++_ulRefCount; }

virtual ULONG STDMETHODCALLTYPE Release( void) {       ULONG ul = --_ulRefCount; if (!ul) delete this; return ul; }

protected: ULONG _ulRefCount; };

HRESULT XMLDummySecurity(IXMLDOMDocument * pXMLDocument) {      HRESULT hr; IObjectWithSite * pObjWithSite = NULL; if (SUCCEEDED(hr = pXMLDocument->QueryInterface(IID_IObjectWithSite, (void **)&pObjWithSite))) {          DummySite * pObj = new DummySite; pObjWithSite->SetSite(pObj); pObjWithSite->Release; pObj->Release; }      return hr; }

Visual Basic Example
Follow these steps to create a dummy security class in your project and attach it as a site to the XML Document object:   Create a new text file called Objwithsite.idl and add the following code into it: [  uuid(FC4801A3-2BA9-11CF-A229-00AA003D7353), version(1.0), helpstring("IObjectWithSite TLB") ] library IOBJWITHSITELib {  [      object, uuid(FC4801A3-2BA9-11CF-A229-00AA003D7352), pointer_default(unique) ]  interface IObjectWithSite : IUnknown {     typedef IObjectWithSite * LPOBJECTWITHSITE; HRESULT SetSite(     [in] IUnknown * pUnkSite      ); HRESULT GetSite(        [in] REFIID riid,         [out, iid_is(riid)] void ** ppvSite); } };                        Use the MIDL utility included with the Platform SDK or Visual Studio to create a Type Library (.tlb) from this IDL file. Add a reference to the resultant type library to the XML project. Create a new empty class in the project called CDummySecurity and set its Instancing property to "PublicNotCreatable." Make sure the XML project is an ActiveX project (ActiveX EXE, ActiveX DLL, and so forth). If your existing project is a standard EXE that uses a default startup form, you'll need to add a Main procedure to your project and load the form from there.</li>  Use the following code to set the fake security object before calling loadXML on the XML Document: Dim objDummySecurity As New CDummySecurity Dim site As IObjectWithSite Set site = objXMLDoc site.SetSite objDummySecurity 'Now you can load the document and external references will be resolved. objXMLDoc.loadXML(strXMLWithDTD) </li></ol>

Keywords: kbbug kbfix kbmsxml250fix kbmsxmlnosweep KB235344

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.