Fog Creek Software
Discussion Board




XML Validity

I believe the .NET framework's System.XML namespace provides an XMLValidatingReader to validate XML.

Not using .NET but with VB6 and the XML parser 3.0 or above, how would one validate an XML document against either the DTD or the schema and not using external validators that are available on the Internet for free. How would one code the validator for an XML document using MSXML parser? Also, I observe an IXMLDOMDocumentType object there in the MSXML parser but do not know how to use it. I am not asking for code. I am asking for a brief explanation of what goes into validating an XML. Does IXMLDOMDocumentType lend any help in that or the procedure for validating XML on your own is very rudimentary?

Plus, when I have my XML document with a DTD in it and I try loading it with MSXML DOMDocument Object, the document returns an invalid (meaning junk and not an XML that is not valid) XML that cannot be parsed. How do I parse the DTD contained in an XML document?

Sathyaish Chakravarthy
Thursday, February 05, 2004

For instance, I got this code from MSDN that just reads the name of the DTD in an XML.

[C++]
#include "tchar.h"
#include "stdio.h"
#import "msxml3.dll"
using namespace MSXML2;

inline void TESTHR( HRESULT _hr )
  { if FAILED(_hr) throw(_hr); }

void main()
{
  try
  {
      IXMLDOMDocumentPtr docPtr;

      //init
      TESTHR(CoInitialize(NULL));
      TESTHR(docPtr.CreateInstance(_T("Msxml2.DOMDocument")));

      // Load a document.
      _variant_t varXml(_T("c:\\book.xml"));
      _variant_t varOut((bool)TRUE);
      varOut = docPtr->load(varXml);
      if ((bool)varOut == FALSE)
      {// Show error description - IXMLDOMParseError sample.
        IXMLDOMParseErrorPtr errPtr = docPtr->GetparseError();
      // Print error details.
      }
      else
      {
        IXMLDOMDocumentTypePtr docTypPtr = docPtr->doctype;
        if (docTypPtr)
        {
            _bstr_t bstrTyp(docTypPtr->name);
            _tprintf(_T("Document type name = %s\n"), (TCHAR*)bstrTyp);
        }
      }
  }
  catch (_com_error &e)
  {
      _tprintf(_T("Error:\n"));
      _tprintf(_T("Code = %08lx\n"), e.Error());
      _tprintf(_T("Code meaning = %s\n"), (TCHAR*) e.ErrorMessage());
      _tprintf(_T("Source = %s\n"), (TCHAR*) e.Source());
      _tprintf(_T("Error Description = %s\n"), (TCHAR*) e.Description());
  }
  catch(...)
  {
      _tprintf(_T("Unknown error!"));
  }
  CoUninitialize();
}

[/C++]


To start with I tried the same thing in VB and this time it recognized my doc's DTD. I realized I did not know how to initialize the IXMLDOMDocumentType object.

[VB]
Private Sub Command1_Click()

Dim xmlDoc As DOMDocument
Set xmlDoc = New DOMDocument

If Not xmlDoc.Load(App.Path & "\Collection.xml") Then
    MsgBox "Unable to load XML"
    Set xmlDoc = Nothing
    Exit Sub
End If

Dim xmlDocType As IXMLDOMDocumentType
Set xmlDocType = xmlDoc.doctype
MsgBox xmlDocType.Name
Set xmlDocType = Nothing
Set xmlDoc = Nothing

End Sub

[/VB]


But I get the feeling that an application trying to validate on the basis of this object IXMLDOMDocumentType will have to parse the DTD just like another XML and read all the nodes and make sense of them, which is going to be very painful. What I expect will be the most horrific excercise will be verifying the XML against the DTD i.e the actual validation which the application will have to handle.

Sathyaish Chakravarthy
Thursday, February 05, 2004

Er, if you're using MSXML, why aren't you just using its own methods for validation?  For instnace, you might want to look in the help file for the topic "Validate an XML Document Against an XML Schema"

jburka
Thursday, February 05, 2004

Hi,

This has not been tested, but we use something along these lines.  Hope this help!

  Dim oXML As MSXML2.FreeThreadedDOMDocument40 
  Dim oxmlSchema As MSXML2.XMLSchemaCache40
  Dim blnValidXML As Boolean   
  Dim sSchemaFile As String 
   
  sSchemaFile = "C:\SomeXmlSchemaFile.xsd"
   
  'Load the Schema
  Set oxmlSchema = New MSXML2.XMLSchemaCache40
   
  oxmlSchema.Add "", sSchemaFile
   
  Set oXML = New MSXML2.FreeThreadedDOMDocument40
  Set oXML.schemas = oxmlSchema
   
  blnValidXML = oxmlMessage.loadXML(sxmlMessage)
  If Not blnValidXML Then
      'Raise Error - String Passed In is not a Valid XML or does not confirm to the XML Schema
      Err.Raise vbObjectError + 1000, "", oXML.parseError.reason
  End If
 
  Set oxmlSchema = Nothing   
  Set oxmlMessage = Nothing

Garett
Thursday, February 05, 2004

Ooops!

s/oxmlMessage/oXML/g

Garett
Thursday, February 05, 2004

Thanks a lot. But for the few typos, it worked like a charm.

What about DTDs now? To test your sample, I generated the XML schema, I didn't write it myself. I have not yet learnt XSD. But I am familiar with DTDs and have written quite many of them. If I have to validate against a DTD, how do I do it with MSXML?

Sathyaish Chakravarthy
Thursday, February 05, 2004

I guess I could try the same path for a DTD, load an external DTD first into an IXMLDOMDocumentType, then create a blank DOMDocument, assign the DTDObject to the docType property of the DocumentObject and then try to load the XML document into the document object.

Am I on the right track?

Sathyaish Chakravarthy
Thursday, February 05, 2004

You could use the <!DOCTYPE> tag within your XML to point to the DTD then do something like this.  Again not tested and I apologize beforehand for any typos. 

Dim oXML As New Msxml2.DOMDocument40
oXML.async = False
oXML.validateOnParse = True
oXML.Load "C:\SomeFile.xml"

Here is an article that provides an example, along with a more thorough explanation.

Garett
Thursday, February 05, 2004

Where's the article, hey?

Sathyaish Chakravarthy
Thursday, February 05, 2004

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/htm/dtd_dev_1fqs.asp

Garett
Thursday, February 05, 2004

*  Recent Topics

*  Fog Creek Home