Search code examples
xmlvbadomxsdmsxml

MSXML VBA: Validating XML against XSD: "The '' namespace provided differs from the schema's targetNamespace."


I’m trying to validate an .XML file against an .XSD file with MSXML 6.0 DOM but on executing the code I’m getting this error message:

Test.xsd#/schema/targetNamespace[1]
"The '' namespace provided differs from the schema's 'http://somewhere.com/root' targetNamespace."

A heavily simplified versions of the .XML and .XSD files also produce the same error:

XML FILE

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:noderoot xmlns:ns2="http://somewhere.com/root">
    <general>
        <year>2011</year>
        <month>02</month>
    </general> 
</ns2:noderoot>

XSD FILE

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://somewhere.com/root" 
            targetNamespace="http://somewhere.com/root" 
            xmlns:xs="http://www.w3.org/2001/XMLSchema" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            elementFormDefault="unqualified" 
            attributeFormDefault="unqualified">

    <xs:complexType name="TYPE_nodeGeneral">
        <xs:sequence>
            <xs:element name="year">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:length value="4"/>
                        <xs:pattern value="\d{4}"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>
            <xs:element name="month">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:length value="2"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>           

    <xs:complexType name="TYPE_noderoot">
        <xs:sequence>
            <xs:element name="general" type="TYPE_nodeGeneral"></xs:element>            
        </xs:sequence>
    </xs:complexType>

    <xs:element name="noderoot" type="TYPE_noderoot"></xs:element>

</xs:schema>

In order to validate the XML file I’m using this code written in VBA (Excel 2010):

Sub XSD_Validation()

   XML_FILE = "I:\Test.xml"    
   XSD_FILE = "I:\Test.xsd"

    Dim xmlDoc As MSXML2.DOMDocument60
    Set xmlDoc = New MSXML2.DOMDocument60
    xmlDoc.async = False
    xmlDoc.validateOnParse = False
    xmlDoc.resolveExternals = False

    xmlDoc.Load XML_FILE

    ' Open XSD file
    Dim obXSD As MSXML2.DOMDocument60
    Set objXSD = New MSXML2.DOMDocument60
    objXSD.async = False
    objXSD.Load XSD_FILE

    ' Populate schema cache
    Dim objSchemaCache As XMLSchemaCache60
    Set objSchemaCache = New MSXML2.XMLSchemaCache60
    objSchemaCache.Add "", objXSD

    ' XSD XML Bind
    Set xmlDoc.Schemas = objSchemaCache

    'Error visualization
    Dim objErr As MSXML2.IXMLDOMParseError
    Set objErr = xmlDoc.Validate()
    If objErr.errorCode <> 0 Then
        Debug.Print "Error parser: " & objErr.errorCode & "; " & objErr.reason
    Else
        Debug.Print "No errors found"
    End If

    Set objErr = Nothing
    Set objXSD = Nothing
    Set objSchemaCache = Nothing
    Set xmlDoc = Nothing

End Sub

The XSD file can be modified but the XML file must remain untouchable.

I've been trying to solve this issue for more than 8 hours with no positive result.

Any help will be greatly appreciated.


Solution

  • Try adding the namespace URI to the schema cache.

    Sub XSD_Validation()
        Dim xmlDoc As MSXML2.DOMDocument60
        Dim objSchemaCache As New XMLSchemaCache60
        Dim objErr As MSXML2.IXMLDOMParseError
    
        objSchemaCache.Add "http://somewhere.com/root", LoadXmlFile("I:\Test.xsd")
    
        Set xmlDoc = LoadXmlFile("I:\Test.xml")
        Set xmlDoc.Schemas = objSchemaCache
    
        Set objErr = xmlDoc.Validate()
        If objErr.errorCode = 0 Then
            Debug.Print "No errors found"
        Else
            Debug.Print "Error parser: " & objErr.errorCode & "; " & objErr.reason
        End If
    End Sub
    
    Function LoadXmlFile(Path As String) As MSXML2.DOMDocument60
        Set LoadXmlFile = New MSXML2.DOMDocument60
    
        With LoadXmlFile
            .async = False
            .validateOnParse = False
            .resolveExternals = False
            .load Path
        End With
    End Function