Tim Hastings - NonHostile (because there's no need)

Weblog and collection of geeky articles.

  Home :: Who? :: Contact :: Links :: Subscribe subscribe
Ryan's ChristeningThe Quiet Before The Baby StormAlex and Jackson visit while Abigail shows off her Play Nest
This code requires a project reference to Microsoft XML 4.0 available from Microsoft's Download Center

This is a very simple example to demostrate the validation of a fragment of XML.
We want a validate than a element called sampleRoot has an attribute called myAttribute that can have a value of either 'animal', 'vegatable' or 'mineral'.

Sample XSD
This XSD defines our schema. We have to give it a namespace, for this example we're using urn:sample
    <!-- two namespaces used, xsd schema and the one we're defining (targetNamespace) -->
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:n="urn:sample"
               targetNamespace="urn:sample">
       
      <!-- define root element -->
      <xs:element name="sampleRoot" type="n:sampleRootType"/>
     
      <!-- define a datatype: sampleRootType -->
      <xs:complexType name="sampleRootType">
        <xs:attribute name="myAttribute" type="n:AnimalVegMineral" use="optional"/>
      </xs:complexType>
     
      <!-- define a Animal/Veg/Mineral data type -->
      <xs:simpleType name="AnimalVegMineral">
        <xs:restriction base="xs:string">
          <xs:enumeration value="animal"/>
          <xs:enumeration value="vegatable"/>
          <xs:enumeration value="mineral"/>
        </xs:restriction>
      </xs:simpleType>

    </xs:schema>

Samples of XML that Reference Our Schema Definition
XML documents that should conform to this schema must declare their namespace. The following fragments conform to the bove schema definition:
    <x:sampleRoot xmlns:x="urn:sample" myAttribute="animal"/>
The following fragments do not.
    <x:sampleRoot xmlns:x="urn:sample" myAttribute="piano"/>
Visual Basic Code to Validate an XML File against an XSD File
This function accepts the paths of two datafiles. An XML Schema Definition and an XML file.

    Private Function Validate(ByVal strXMLPath As String, _
                              ByVal strXSDPath As String) As Boolean

        Dim objSchemas As MSXML2.XMLSchemaCache40
        Dim objXML As MSXML2.DOMDocument40
        Dim objXSD As MSXML2.DOMDocument40
        Dim strNamespace As String
        Dim objErr As MSXML2.IXMLDOMParseError
       
        ' load XSD as DOM to populate in Schema Cache
        Set objXSD = New MSXML2.DOMDocument40
        objXSD.async = False
        If Not objXSD.Load(strXSDPath) Then
            Err.Raise 1, "Validate", "Load XSD failed: " & objXSD.parseError.reason
        Else
            ' get namespace name from XSD targetNamespace attribute
            strNamespace = objXSD.documentElement.getAttribute("targetNamespace")
        End If
       
        ' populate schema cache
        Set objSchemas = New MSXML2.XMLSchemaCache40
        objSchemas.Add strNamespace, objXSD
       
        ' load XML file (without validation - that comes later)
        Set objXML = New MSXML2.DOMDocument40
        objXML.async = False
        objXML.validateOnParse = False
        objXML.resolveExternals = False
       
        ' load XML, without any validation
        If Not objXML.Load(strXMLPath) Then
            Err.Raise 1, "Validate", "Load XML failed: " & objXML.parseError.reason
        End If
       
        ' bind Schema Cache to DOM
        Set objXML.schemas = objSchemas
       
        ' does this XML measure up?
        Set objErr = objXML.Validate()
       
        ' any good?
        Validate = (objErr.errorCode = 0)
        If objErr.errorCode <> 0 Then
            Err.Raise 1, "Validate", objErr.reason
        End If

    End Function

The above function could easily be adapted to load XML and XSD from string variables as opposed to data files.

For situations where multiple XML validations are required, repeatedly populating and destroying the schema cache is clearly ineffecient and could be optimised.

Examples Calling this Function
    Validate App.Path & "\sc-valid-tjh.xml", App.Path & "\sc-tjh-min.xsd"
    Validate App.Path & "\sc-valid.xml", App.Path & "\sc-tjh-min.xsd"
6 comments, Visual Basic 6, Thursday, April 15, 2004 16:24

Timeline Navigation for Visual Basic 6 posts
VB6: Convert HTML into Searchable Text using Regular Expressions (made 3 weeks later)
VB6: Validate XML against XSD in Visual Basic (this post, made Thursday, April 15, 2004 16:24)
VB6: Read XML from a Visual Basic Resource and Return Root Element (made 52 minutes earlier)


Comments
Hi,

I have a question: I've tried implementing this code with MSXML6 (replacing the 40's with 60's) and I have the follwing problem,

if the XML file has the declaration:

<fb:pratiche xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.fbk.it/pratiche file:///w:/xml/xsd/pratiche/Master.xsd" xmlns:fb="http://www.fbk.it/pratiche">

it refuses to validate saying :
error 1072897500 - "The node is niether valid nor invalid because no DTD/Schema declaration was found"

however, if I remove the xsi namespace, it works perfectly.

Do you have any idea what might be causing this?

Posted by: nick brandwood on Monday, March 6, 2006 16:19

Posted by: zisco on Wednesday, January 3, 2007 15:57
how we can puts check on email address whter an email address is valid or invalid?

Posted by: syed on Tuesday, August 14, 2007 12:05
Hi,

This example is a good help. Thanks.

I only had the following problem :

' does this XML measure up?
Set objErr = objXML.Validate()

If objErr.errorCode <> 0 Then
' worked fine
Debug.Print "errorCode " & objErr.errorCode
Debug.Print "reason " & objErr.reason

' I didn't manage to get following information
Debug.Print "filepos " & objErr.filepos
Debug.Print "Line " & objErr.Line
Debug.Print "linepos " & objErr.linepos
Debug.Print "srcText " & objErr.srcText
Debug.Print "url " & objErr.url
end if


Then I tried following code :

objXML.async = False
objXML.validateOnParse = True
objXML.resolveExternals = True

If Not objXML.Load(strXMLPath) Then
' In this case I could get the information from every member
Debug.Print "errorCode " & objXML.parseError.errorCode
Debug.Print "reason " & objXML.parseError.reason
Debug.Print "filepos " & objXML.parseError.filepos
Debug.Print "Line " & objXML.parseError.Line
Debug.Print "linepos " & objXML.parseError.linepos
Debug.Print "srcText " & objXML.parseError.srcText
Debug.Print "url " & objXML.parseError.url
end if

I don't understand, why it is like that. But you might have an answer.


P.S : objXML.resolveExternals = True solves the problem with MSXML6



Posted by: odCaplan on Monday, September 3, 2007 08:17
I also use the dll file msxml6.dll but I get the error:
error 1072897500 - "The node is niether valid nor invalid because no DTD/Schema declaration was found"

The beginning of the xsd file looks like:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Tmp" targetNamespace="urn:Tmp.xsd" xmlns:mstns="urn:Tmp.xsd" xmlns="urn:Tmp.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" attributeFormDefault="qualified" elementFormDefault="qualified">

Does anyone know what the problem is?

Posted by: Mark on Thursday, April 17, 2008 15:22
Hi,

I've used your VB code on a project I'm working on and it works perfectly. Thank you.
At the moment, if I validate an XML file with more than one error, the function returns a message detailing the error found.
Would it be possible to modify this code so that the validation process continues on after the first error is found and returns a message detailing all errors found?
e.g.
Error parsing '2008-13-07' as date datatype.
The element: '{urn:iso:std:iso:20022:tech:xsd:pacs.008.001.01}IntrBkSttlmDt' has an invalid value according to its data type.
Error parsing '2360.0q' as decimal datatype.
The element: '{urn:iso:std:iso:20022:tech:xsd:pacs.008.001.01}IntrBkSttlmAmt' has an invalid value according to its data type.

Thanks in advance.


Posted by: Shaymoh on Friday, June 6, 2008 13:34

Post a Comment
Name:  Home page and email address are optional.
  Email addresses will not be displayed or spammed!
Remember these details
Email:
Home Page:
Comment:
Comments cannot contain HTML, URLs will be formatted into hyperlinks.
I reserve the right to remove any comments for any reason.