Can't cause MSXML 6 XSD validation error
-
Monday, July 30, 2012 9:50 PM
Hi folks,
VBA in Excel 2007, MSXML 6 - I'm trying to test that validation against an XSD I developed will fail if there are problems in documents associated with the schema. I've been able to trigger validation errors against this schema using the Eclipse (Helios) XML tools, but I can't seem to cause MSXML 6 validation to fail unless it's something like basic well-formedness of the data document. The schema document itself loads and validates without problems in MSXML 6. I've tried 1) setting parseOnLoad true for the data document, 2)doing a manual validate() on the data document, and also adding the schema to a schemaCache and validating against that. None of them will trip, again, unless it's a basic well-formedness problem.
It's been a while since I've had to do this, and I'm guessing I'm somehow not getting the namespaces wired correctly. Would appreciate it if someone could let me know if the cause of the problem jumps out at them.
Here's the test code:
Sub checkSchema() Dim vMyErr As Variant Dim oXSDDoc As DOMDocument60 Set oXSDDoc = New DOMDocument60 oXSDDoc.async = False 'Load XML Schema from a file oXSDDoc.validateOnParse = True oXSDDoc.Load (ThisWorkbook.Path & "\PSTTLTD2.xsd") If oXSDDoc.parseError.ErrorCode <> 0 Then Set vMyErr = oXSDDoc.parseError MsgBox "XML parsing error " + vMyErr.reason End If oXSDDoc.Validate If oXSDDoc.parseError.ErrorCode <> 0 Then Set vMyErr = oXSDDoc.parseError MsgBox "XML parsing error " + vMyErr.reason End If 'Load XML document from a file Dim oSourceDoc As DOMDocument60 Set oSourceDoc = New DOMDocument60 oSourceDoc.async = False oSourceDoc.validateOnParse = True oSourceDoc.Load (ThisWorkbook.Path & "\XMLFinalSchemaTestDoc.xml") If oSourceDoc.parseError.ErrorCode <> 0 Then Set vMyErr = oSourceDoc.parseError MsgBox "XML parsing error " + vMyErr.reason End If oSourceDoc.Validate If oSourceDoc.parseError.ErrorCode <> 0 Then Set vMyErr = oSourceDoc.parseError MsgBox "XML parsing error " + vMyErr.reason End If 'Validate with Schema Cache 'Reload schema into cache. Set oXSDDoc = New DOMDocument60 oXSDDoc.async = False oXSDDoc.Load (ThisWorkbook.Path & "\PSTTLTD2.xsd") Set oSchemaCache = New XMLSchemaCache60 oSchemaCache.Add "urn:histogramList", oXSDDoc Set oSourceDoc.Schemas = oSchemaCache oSourceDoc.Validate If oSourceDoc.parseError.ErrorCode <> 0 Then Set vMyErr = oSourceDoc.parseError MsgBox "XML parsing error " + vMyErr.reason End If End Sub
Here's the schema:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema targetNamespace="urn:histogramList" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:hL="urn:histogramList" elementFormDefault="qualified"> <xs:element name="HistogramList"> <xs:complexType> <xs:sequence> <xs:element name="Histogram" minOccurs="1" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="DataRecord" minOccurs="1" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="Start" type="xs:integer" minOccurs="1" maxOccurs="1"/> <xs:element name="Stop" type="xs:integer" minOccurs="1" maxOccurs="1"/> <xs:element name="NumberOf" type="xs:integer" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="ResourceName" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="([a-zA-Z]([a-zA-Z0-9]|_|-)*){1}(\.([a-zA-Z]([a-zA-Z0-9]|_|-)*){1})*"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="HistogramType" type="xs:NMTOKENS" use="required"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>Here's a snippet of the XML document that I can't get to fail validation in MSXML - note that there is a missing required attribute on the <Histogram> element, and the first <DataRecord> element is actually misnamed "xDataRecord":
<?xml version="1.0"?> <HistogramList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:histogramList PSTTLTD2.xsd" xmlns="urn:histogramList"> <Histogram HistogramType="Net Usage"> <xDataRecord><Start>7632000</Start><Stop>7660800</Stop><NumberOf>0</NumberOf></xDataRecord> <DataRecord><Start>7660800</Start><Stop>7689600</Stop><NumberOf>0</NumberOf></DataRecord> <DataRecord><Start>7689600</Start><Stop>7718400</Stop><NumberOf>0</NumberOf></DataRecord> <DataRecord><Start>7718400</Start><Stop>7747200</Stop><NumberOf>-6</NumberOf></DataRecord>
The XSD file is co-located with both the spreadsheet containing the VBA code, and the XML data document, so, as near as I can tell, the filename without a path should be valid (in any event, nothing complains that it can't locate the XSD, and the same simple location format reference also works in Eclipse when the XSD is in the same workspace). However, note that I also tried a file reference in the following (example) format for the schema location:
urn:MyData file://C://Documents and Settings//All Users//Application Data//My Application//MyData.xsd
The longer format didn't seem to make any difference.)
Thanks for any help!
- Edited by linearprism Monday, July 30, 2012 9:54 PM Corrected formatting glitch in VBA code block.
All Replies
-
Tuesday, July 31, 2012 12:02 PM
When I used MSXML 6 to perform schema validation then I simply added the schema to a schema collection, set that as the schemas property and validated while loading the document; here is a sample (with VBScript but of course the API to use is the same with VBA and early binding):
Dim xmlDoc, schemaCache Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0") Set schemaCache = CreateObject("Msxml2.XMLSchemaCache.6.0") schemaCache.add "urn:histogramList", "test2012073101.xsd" xmlDoc.schemas = schemaCache xmlDoc.validateOnParse = True xmlDoc.setProperty "MultipleErrorMessages", True If xmlDoc.load("test2012073101.xml") then WScript.Echo "Document is well-formed and valid." Else For Each pErr In xmlDoc.parseError.allErrors WScript.Echo "Error " & pErr.reason & " for " & pErr.errorXPath Next End IfNow with the input XML being
<?xml version="1.0"?> <HistogramList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:histogramList test2012073101.xsd" xmlns="urn:histogramList"> <Histogram HistogramType="Net Usage"> <xDataRecord><Start>7632000</Start><Stop>7660800</Stop><NumberOf>0</NumberOf></xDataRecord> <DataRecord><Start>7660800</Start><Stop>7689600</Stop><NumberOf>0</NumberOf></DataRecord> <DataRecord><Start>7689600</Start><Stop>7718400</Stop><NumberOf>0</NumberOf></DataRecord> <DataRecord><Start>7718400</Start><Stop>7747200</Stop><NumberOf>-6</NumberOf></DataRecord> </Histogram> </HistogramList>
and the schema being as you posted I get the following error messages as the output:
Error Erforderliches Attribut 'ResourceName' fehlt. for /*[local-name()="HistogramList" and namespace-uri()="urn:histogramList"]/*[local-name()="Histogram" and namespace-u ri()="urn:histogramList"][1] Error Der Inhalt des Elements '{urn:histogramList}xDataRecord' ist gemäß dem Inhaltsmodell des übergeordneten Elements ' {urn:histogramList}Histogram' nicht gültig. Erwartet: {urn:histogramList}DataRecord. for /*[local-name()="HistogramList" and namespace-uri()="urn:histogramList"]/*[local-name()="Histogram" and namespace-u ri()="urn:histogramList"][1]/*[local-name()="xDataRecord" and namespace-uri()="urn:histogramList"][1]Sorry, I am on a German version of Windows here so the messages MSXML outputs are German but it correctly complaints about the missing attribute and the incorrect child element.
If you don't want to load the scheme explicitly then I think you can also do
Dim xmlDoc, schemaCache Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0") 'Set schemaCache = CreateObject("Msxml2.XMLSchemaCache.6.0") 'schemaCache.add "urn:histogramList", "test2012073101.xsd" 'xmlDoc.schemas = schemaCache xmlDoc.validateOnParse = True xmlDoc.resolveExternals = True xmlDoc.setProperty "MultipleErrorMessages", True If xmlDoc.load("test2012073101.xml") then WScript.Echo "Document is well-formed and valid." Else For Each pErr In xmlDoc.parseError.allErrors WScript.Echo "Error " & pErr.reason & " for " & pErr.errorXPath Next End IfThat way the schema is loaded from the location given in the schemaLocation attribute.
MVP Data Platform Development My blog
- Marked As Answer by linearprism Tuesday, July 31, 2012 6:29 PM
-
Tuesday, July 31, 2012 6:33 PM
Thanks, Martin.
I've got it working in VBA if I follow your steps in those precise sequences.

