Link to home
Start Free TrialLog in
Avatar of NikWhitfield
NikWhitfield

asked on

XML / Schema validation - need error node

Hi -

    I'm running validation for an XML file against an xsd schema using MSXML4. I do this using the following code:

Dim objReader As New MSXML2.SAXXMLReader40  '-  Create a SAX reader.
Dim objValidator As clsXMLEventHandler      '-  Create an instance of the class module that implements the IVBSAXErrorHandler interface

Const VALIDATE_FEATURE As String = "schema-validation"
Const EXHAUSTIVE_FEATURE As String = "exhaustive-errors"
Const VALIDATE_TYPE_PROPERTY As String = "schemas"
 
    'Assume failure
    ValidateXML = False
   
    'Instantiate the event handler
    Set objValidator = New clsXMLEventHandler
   
    'Setup the validator
    objValidator.XML = pobjDOMDoc.XML

    'Configure the SAX reader to validate the XML document.
    With objReader
        .putFeature VALIDATE_FEATURE, True
        .putFeature EXHAUSTIVE_FEATURE, True
        .putProperty VALIDATE_TYPE_PROPERTY, mobjSchemaCache
        'Assign an instance of the MyValidator class to the errorHandler property of the SAX reader.
        Set .ErrorHandler = objValidator
        'Parse and validate the xml.
        .parse pobjDOMDoc.XML
    End With

This uses an event handler class which implements IVBSAXErrorHandler. This catches validation errors in subroutines like this one:

IVBSAXErrorHandler_error(ByVal oLocator As MSXML2.IVBSAXLocator, strErrorMessage As String, ByVal nErrorCode As Long)

This is great and gives me some useful info. However, what I could really do with is the Node object for which the error was thrown.

Does anyone know how I would go about getting hold of the node object? I've got the line number and column, and a copy of the .XML text - how would I go about finding the required node??

Answers on a postcard....

Thanks, Nik
Avatar of NikWhitfield
NikWhitfield

ASKER

Points increased..
Postcard from Rat's Hole:

Having a nice time, wish you were here!

Rat.

Tell me different if I'm stupid, but SAX does not create nodes like DOM. So how can the event signify the node?
NikWhitfield,

Of course BigRat is correct.

If you look at the MSXML API, a "node" is actually an IXMLDOMNode object, which gives you a clue as to which mechanism is used to create them. SAX implementations are event-driven, and doesn't create any internal representation of the document (it just tells you when certain conditions are encountered while processing the document in a serial fasion), whereas DOM implementations will parse and internalise the entire document before making it available to applications through the various hierarchically-organised DOM node types.

Regards,
WMB
Both correct.

My thoughts were that there may be some mechanism between SAX and DOM, such that it is possible to identify a node based on the line number and column number returned in the IVBSAXLocator.

Having looked around a while, nothing like this does exist! I've written something with some degree of success, but not a complete solution by any means.
Is the document so big that it couldn't be loaded into a DOM?
Nope -

  but with the SAX parser, I can get multiple errors on validation, i.e. parse all errors / warnings in one go, as oppose to find an error, raise it, correct problem, find next error, etc.
Yes, I see. Then you can fix them all at once rather than one at a time (ever tried programming with Borland Turbo Pascal?).

Still other than "last-tag-seen" there's not much else!
I think the aforementioned 'last-tag-seen' is the only way to go... unfortunately, it seems that MSXML sometimes returns errors against the wrong attribute, for example ...

Multiple error validation is damned important - for all you know, there are 6000 errors in your schema! You could get pretty pissed off with not knowing the total before you set out to correct them all...
A request has been made by the Asker that this question be deleted.

EXPERTS: Please leave your thoughts here; I will return in seven (7) days to resolve the question.

Netminder
CS Moderator
OK, but it's a pity about the cheese!
Bigrat,

    sorry, but I managed to implement this functionality myself (with some ultra unpleasant code!). If you'd like to see it, then let me know and I'll forward you the stuff.

Nik
Doesn't IVBSAXErrorHandler give you what you need?
What I mean to say is, this looks like the same error handler provided by Xerces, etc, and it returns line number, position and node name in its error report.

What other information are you looking for? Maybe there's a cleaner workaround? What is your current workaround?
Not that I can find
Xerces, of course, also has a DOM error handler which would give you what you need if you were able to use it, but I'm guessing that's not an option?
Xerces, of course, also has a DOM error handler which would give you what you need if you were able to use it, but I'm guessing that's not an option?
Xerces, of course, also has a DOM error handler which would give you what you need if you were able to use it, but I'm guessing that's not an option?
Actually, Nik, I realised what I just wrote isn't strictly true -- Xerces (actually the w3 DOM API) uses the SAX error handler to report DOM errors, so you get the exact same error info, but you would get all of them.

I guess the key problem is that DOM won't expose any Node objects until the document is completely parsed and built.
The basic problem is that SAX will not return an actual DOM node object. I've done a load of gymnastics to find an appropriate node using the error position in the XML file. It's really convoluted, but returns a node in the end, if indeed it was a node which errored (I'm not currently concerned with attributes).
ASKER CERTIFIED SOLUTION
Avatar of Mindphaser
Mindphaser

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial