Visual Basic Grumble Grumble
So I’m trying to create a XML document from VB using Microsoft’s implementation of DOM. It seems pretty simple. About the same as every other implementation of DOM I’ve used. However I’m running into two rather annoying problems:
But before that, here is my schema:
<?xml version="1.0" encoding="UTF-8"?> <!-- edited with XMLSpy v2005 rel. 3 U (http://www.altova.com) --> <xs:schema xmlns="http://jclement.ca/xml/simple" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://jclement.ca/xml/simple" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0-rc1"> <xs:element name="AFE" type="AFEType"/> <xs:complexType name="AFEType"> <xs:sequence> <xs:element name="AFEID" type="xs:positiveInteger"/> <xs:element name="AFENumber" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema>
And I’m trying to create a simple valid XML document that looks like this:
<?xml version="1.0"?> <AFE xmlns="http://jclement.ca/xml/simple"><AFEID>1</AFEID><AFENumber>C001</AFENumber></AFE>
Problem #1: My XML schema has a targetNamespace defined. For my output document I would like to define the default namespace to be that namespace (ie. I’d prefer not to have to prefix all my elements). So the code for this seems simple:
Dim doc As New DOMDocument40
Dim version As IXMLDOMProcessingInstruction
Dim attr As IXMLDOMAttribute
Dim el As IXMLDOMElement
doc.preserveWhiteSpace = False
doc.async = False
' add xml version element
Set version = doc.createProcessingInstruction("xml", "version=""1.0""")
doc.appendChild version
' add base AFE element
doc.appendChild doc.createElement("AFE")
' set default namespace to that of schema
Set attr = doc.createAttribute("xmlns")
attr.nodeValue = "http://jclement.ca/xml/simple"
doc.documentElement.Attributes.setNamedItem attr
Set el = doc.createElement("AFEID")
el.appendChild doc.createTextNode("1")
doc.documentElement.appendChild el
Set el = doc.createElement("AFENumber")
el.appendChild doc.createTextNode("C001")
doc.documentElement.appendChild el
MsgBox doc.xml
Unfortunately the output of the program is this:
<?xml version="1.0"?> <AFE xmlns="http://jclement.ca/xml/simple"><AFEID xmlns="">1</AFEID><AFENumber xmlns="">C001</AFENumber></AFE>
The output is mostly what I expect except for the extra “xmlns=” attribute added to the child tags. This is causing the validator to look in the default namespace instead of the correct “http://jclement.ca/xml/simple” namespace. This does not seem right to me. I also tried identical code in Python and .NET and neither of them have this behaviour. They do what I expect and produce output where the child elements do not specify a namespace and instead inherit from the parent element.
I’ve tried messing around with the element creation but I can’t find any way of changing their namespace. The only work around I have is to change the document to something like this:
<?xml version="1.0"?> <afe:AFE xmlns:afe="http://jclement.ca/xml/simple"><afe:AFEID>1</AFEID><afe:AFENumber>C001</AFENumber></AFE>
Which isn’t that hard to do in code and the DOM library no longer adds the blank xmlns stuff but it’s also kinda ugly.
Also this works fine if there is no targetNamespace on the schema.
To make like more exciting I’ve scoured the Internet for documentation on this and have yet to find anything useful. Microsoft doesn’t even have support forums for VB6 anymore. I found a book on VB6 and XML but it’s long since out of print. They joys of using retired development tools!
Problem #2:
I also wanted my app to validate my schema just so I can be sure I am exporting good data. This also “seems” easy enough.
' Now to try validation using doc from previous
Dim schemaCache As New XMLSchemaCache40
Dim result As IXMLDOMParseError
schemaCache.Add "http://jclement.ca/xml/simple", "c:\simple.xsd"
Set doc.schemas = schemaCache
Set result = doc.Validate
If result.errorCode 0 Then
MsgBox "XML Validation Error:" & result.reason
End If
Which produces:
XML Validation Error:Validate failed because the root element had no associated DTD/schema.
Well it seems to me I do have an associated schema and indeed if I remove the namespace from the XSD and the schemaCache.add line it all just works.
I find it surprising that these are actually bugs in the microsoft XML libraries as it seems that there must be lots of people using these. Could it be nobody else uses XML schemas?
Anyways. Very annoying. I know exactly what I want to do but I just can’t convince VB to do it. Grrr.
Update: Example VB6 Project (unzip to c:\test).
