- Introducing MSXML
- Concepts and Observations
- XML Schema Examples
- MSXML Fundamentals
- Schema Object Model (SOM)
- Validation
- Example: XML Schema Tree
18.7 -Example: XML Schema Tree
Now that we have examined some of the features of the Microsoft XML Core Services, we can pull these concepts together in a single application. To illustrate the XML Schema features of MSXML, you can build a simple tool in Visual Basic to examine an XML schema document and validate documents against it.
Before building the project, you must have already installed the MSXML 4.0 components on the development machine. You can find these components, which are both free and redistributable, at the Microsoft Developer Network site, specifically at:
http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/ 001/766/msdncompositedoc.xml
After you have downloaded and executed the installation, you can develop applications by using MSXML.
The XML Schema Tree sample was created in Visual Basic 6.0 as a Standard Executable project. The project has a single form, SchemaTreeForm, that provides menus and displays the schema information. The sample code can be downloaded from
http://www.XMLSchemaReference.com/examples/Ch18.
Figure 18.4 shows the design-time view of the SchemaTreeForm. It consists of a menu, a tree view, an image list, and a common dialog control.
To create this project, first select a new Standard Executable. Next you must include the necessary components to build the project. The project requires three additional libraries: MSXML 4.0, the Microsoft Common Dialog Control, and the Microsoft Windows Common Controls. The Microsoft Common Dialog Control contains the common file Open/Save dialog box used in Windows applications, and the Common Controls library holds both the tree view and the image list controls. To load these into your application, you must configure the project file to use them. You can add MSXML support to this project just as shown in Figure 18.2. Under the Visual Basic menu, select the Project menu, and then select References to add the MSXML 4.0 components. Add the other two libraries in a similar fashion: From the Project\Components check list, select both the Microsoft Common Dialog Control and the Microsoft Windows Common Controls.
FIGURE 18.4 XML Schema Tree form at design time.
Depending on the system you are running, you might have different versions of the Common Dialog and Common Controls libraries. The feature set used in this application is common to all versions of these libraries, so just select the ones available on your machine.
Now that you have configured your project to use all the necessary libraries, you can examine the application. The tree view, treeSchema, displays the schema contents whenever the File\Open Schema menu item is selected. The application fills the tree with items for the various element types, attribute types, and other parts of the XML schema. The other menu items let users select an XML document to be validated against the loaded schema, by using either the DOM or SAX2 features. The common dialog box allows users to browse for files, and the image list provides icons for the tree view items.
The code for the Schema Tree application is shown in the following listings. Listing 18.12 begins the code for the form shown in Figure 18.4. Loading and selecting an XML schema file and resizing the windows are handled here in code.
LISTING 18.12 SchemaTreeForm.frm Code Part 1
'SchemaTreeForm.frm ' 'Tree view representation of an XML schema using MSXML and SOM Private m_schemaCache As XMLSchemaCache40 Private Sub Form_Load() status.SimpleText = "No schema" Set m_schemaCache = Nothing End Sub Private Sub Form_Resize() treeSchema.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight End Sub Private Sub IDM_FILEEXIT_Click() Set m_schemaCache = Nothing Unload Me End Sub Private Sub IDM_FILEOPEN_Click() On Error GoTo OpenErr status.SimpleText = "Working.." treeSchema.Nodes.Clear Set m_schemaCache = New XMLSchemaCache40 Dim docSchema As DOMDocument40 Dim schema As ISchema Dim strTargetNS As String Set docSchema = New DOMDocument40 docSchema.async = False docSchema.validateOnParse = False Dim strFile As String filedlg.ShowOpen If filedlg.FileName = "" Then Exit Sub strFile = filedlg.FileName If (docSchema.Load(strFile)) Then status.SimpleText = "Loaded " & strFile Else Dim docError As IXMLDOMParseError MsgBox docError.reason, vbCritical, "Schema Tree" Exit Sub End If Dim elemDoc As IXMLDOMElement Dim attr As IXMLDOMAttribute Set elemDoc = docSchema.documentElement Set attr = elemDoc.getAttributeNode("targetNamespace") strTargetNS = "" If attr Is Nothing = False Then strTargetNS = attr.Value End If m_schemaCache.Add strTargetNS, docSchema Set schema = m_schemaCache.getSchema(strTargetNS) FillSchemaTree schema, treeSchema Exit Sub OpenErr: MsgBox Err.Description, vbCritical, "Schema Tree" status.SimpleText = "No schema" Set m_schemaCache = Nothing Exit Sub End Sub
Listing 18.13 continues the form code. The subroutine FillSchemaTree uses the SOM to traverse the contents of the XML schema and load each set of parts into the tree view. Beginning with the ISchema interface, this routine accesses the properties of ISchema and walks the returned ISchemaItemCollection interfaces.
LISTING 18.13 SchemaTreeForm.frm Code Part 2
'Fill a standard TreeView with a tree representation of an XML ' Schema as returned by the MSXML SOM ISchema interface 'This code currently only loads the list of elements, ' attributes, and types Public Sub FillSchemaTree(schema As ISchema, tree As TreeView) If schema Is Nothing Then Exit Sub If tree Is Nothing Then Exit Sub tree.Nodes.Clear Dim nodeRoot As Node Dim nodeCurr As Node Dim strRoot As String strRoot = schema.Name If strRoot = "" Then strRoot = "<schema>" Set nodeRoot = tree.Nodes.Add(,,, strRoot, 1) 'Elements Dim nodeElemGroup As Node Set nodeElemGroup = tree.Nodes.Add(nodeRoot.Index, _ tvwChild, , "<elements>", 2) Dim elem As ISchemaElement For Each elem In schema.elements Dim nodeElem As Node Set nodeElem = tree.Nodes.Add(nodeElemGroup.Index, _ tvwChild,, elem.Name, 2) Next elem 'Attributes Dim nodeAttrGroup As Node Set nodeAttrGroup = tree.Nodes.Add(nodeRoot.Index, _ tvwChild,, "<attributes>", 3) Dim attr As ISchemaAttribute For Each attr In schema.Attributes Dim nodeAttr As Node Set nodeAttr = tree.Nodes.Add(nodeAttrGroup.Index, _ tvwChild,, attr.Name, 3) Next attr 'Types Dim nodeTypeGroup As Node Set nodeTypeGroup = tree.Nodes.Add(nodeRoot.Index, _ tvwChild,, "all types", 5) Dim nodeSimpleTypeGroup As Node Set nodeSimpleTypeGroup = tree.Nodes.Add(_ nodeTypeGroup.Index, tvwChild,, "simple types", 5) Dim nodeComplexTypeGroup As Node Set nodeComplexTypeGroup = tree.Nodes.Add(_ nodeTypeGroup.Index, tvwChild,, "complex types", 4) Dim t As ISchemaType For Each t In schema.types Dim nodeType As Node If t.itemType = SOMITEM_COMPLEXTYPE Then Dim ct As ISchemaComplexType Set ct = Nothing Set ct = t Set nodeType = tree.Nodes.Add(_ nodeComplexTypeGroup.Index, tvwChild,,_ t.Name, 4) End If If t.itemType = SOMITEM_SIMPLETYPE Then Set nodeType = tree.Nodes.Add(_ nodeSimpleTypeGroup.Index, tvwChild,, t.Name, 5) End If Next t 'Expand the schema element nodeRoot.Expanded = True End Sub
Listing 18.14 shows the last portion of form code: the menu handlers for the validation. These routines handle the validation by DOM or SAX, respectively. For both validations, the XMLSchemaCache40 is used to select the schemas in question. The DOM validation uses the schemas property of the DOMDocument40, whereas the SAX2 validation uses the getProperty method of SAXXMLReader40. In addition, in both cases you must make sure validation is active. When using the DOM, you activate validation using the validateOnParse property, and when using SAX, the getFeature method is used.
LISTING 18.14 SchemaTreeForm.frm Code Part 3
Private Sub IDM_FILEVALIDATEDOM_Click() Dim doc As DOMDocument40 Dim docError As IXMLDOMParseError If m_schemaCache Is Nothing Then MsgBox "No schema is loaded", vbCritical, "Schema Tree" Exit Sub End If Set doc = New DOMDocument40 doc.async = False doc.validateOnParse = True Set doc.schemas = m_schemaCache Dim strFile As String filedlg.ShowOpen If filedlg.FileName = "" Then Exit Sub strFile = filedlg.FileName Dim b As Boolean b = doc.Load(strFile) Set docError = doc.parseError If (docError.errorCode = 0) Then MsgBox _ "The document is valid according to the schema.", _ vbOKOnly, "Schema Tree" Else MsgBox docError.reason, vbCritical, "Schema Tree" End If Set doc = Nothing End Sub Private Sub IDM_FILEVALIDATESAX_Click() On Error GoTo SaxErr Dim sax As SAXXMLReader40 If m_schemaCache Is Nothing Then MsgBox "No schema is loaded", vbCritical, "Schema Tree" Exit Sub End If Set sax = New SAXXMLReader40 Dim handler As SAXTest Set handler = New SAXTest Dim strFile As String filedlg.ShowOpen If filedlg.FileName = "" Then Exit Sub strFile = filedlg.FileName sax.putFeature "schema-validation", True sax.putProperty "schemas", m_schemaCache Set sax.contentHandler = handler Set sax.errorHandler = handler sax.parseURL strFile Exit Sub SaxErr: MsgBox Err.Description Exit Sub End Sub
The validation is determined by the errorsor lack thereofthat occur during parsing. Once again, DOM code just checks the parseError, whereas SAX2 relies on the handlers being used. The handler for the Schema Tree application is a Visual Basic class defined in Listing 18.15. This class, SAXTest, resembles the handler shown in Listing 18.4. With both content and error handling combined in the SAXTest class, the SAXTest class receives all the notifications needed to validate with SAX. Just as in Listing 18.4, the handler has a number of empty methods that exist only to make sure you fully implement the interfaces you support.
LISTING 18.15 SAXTest.cls (SAX Validation Handler)
'SAXTest 'SAX Handler for XML Schema Validation Implements IVBSAXContentHandler Implements IVBSAXErrorHandler Private Sub IVBSAXContentHandler_characters(strChars As String) End Sub Private Property Set IVBSAXContentHandler_documentLocator(_ ByVal RHS As MSXML2.IVBSAXLocator) End Property ' Document is validated against the XML Schema Private Sub IVBSAXContentHandler_endDocument() MsgBox "The document is valid according to the schema.", _ vbOKOnly, "Schema Tree" End Sub Private Sub IVBSAXContentHandler_endElement(_ strNamespaceURI As String, strLocalName As String, strQName As String) End Sub Private Sub IVBSAXContentHandler_endPrefixMapping(_ strPrefix As String) End Sub Private Sub IVBSAXContentHandler_ignorableWhitespace(_ strChars As String) End Sub Private Sub IVBSAXContentHandler_processingInstruction(_ strTarget As String, strData As String) End Sub Private Sub IVBSAXContentHandler_skippedEntity(_ strName As String) End Sub Private Sub IVBSAXContentHandler_startDocument() End Sub Private Sub IVBSAXContentHandler_startElement(_ strNamespaceURI As String, strLocalName As String, _ strQName As String, _ ByVal oAttributes As MSXML2.IVBSAXAttributes) End Sub Private Sub IVBSAXContentHandler_startPrefixMapping(_ strPrefix As String, strURI As String) End Sub ' Validation failed for the reason indicated by parameters Private Sub IVBSAXErrorHandler_error(_ ByVal oLocator As MSXML2.IVBSAXLocator, _ strErrorMessage As String, ByVal nErrorCode As Long) MsgBox strErrorMessage, vbCritical, "Schema Tree" End Sub Private Sub IVBSAXErrorHandler_fatalError(_ ByVal oLocator As MSXML2.IVBSAXLocator, _ strErrorMessage As String, ByVal nErrorCode As Long) MsgBox strErrorMessage, vbCritical, "Schema Tree" End Sub Private Sub IVBSAXErrorHandler_ignorableWarning(_ ByVal oLocator As MSXML2.IVBSAXLocator, _ strErrorMessage As String, ByVal nErrorCode As Long) End Sub
With this code, we have a minimal XML schema explorer and document validator. Figures 18.5 and 18.6 show the XML Schema Tree loading an XML schema. Items in the tree are given different locations and icons depending on their types. This user interface provides a view of the schema hierarchy.
FIGURE 18.5 XML Schema Tree in action.
FIGURE 18.6 Validation error for badaddress.xml.
When you load the XML document badaddress.xml, the validation code fails because of the missing customerID attribute in that document. Figure 18.6 shows the message box displayed by the XML Schema Tree application when badaddress.xsd fails to validate against the address schema. This error is caught using the same error-checking code shown in Listing 18.15.