XML

XMLDOMDocument2, XMLDOMSchemaCache, and XMLDOMSelection Objects

The XMLDOMDocument2 object implements the IXMLDOMDocument2 interface. This interface is an extension of the IXMLDOMDocument interface that supports schema caching and validation. The IXMLDOMDocument2 interface inherits all the original properties and methods of the IXMLDOMDocument interface and adds the following new properties:

Extended IXMLDOMDocument2 Properties

Name Description
namespaces Returns a list of all of the namespaces in the document as an XMLDOMSchemaCollection(schemaCache object)
schemas Locates all the schema documents using the XMLDOMSchemaCollection (schemaCache object)

The XMLSchemaCache object which implements the IXMLDOMSchemaCollection interface contains information about the schemas and namespaces used by an XML document. This interface has the following property and methods:

IXMLDOMSchemaCollection Property

Name Description
length Returns the number of namespaces that are currently in the collection

IXMLDOMSchemaCollection Methods

Name Description
add (namespaceURI, schema)

Adds a new schema to the schema collection.

The specified schema is associated with the given namespace URI.

addCollection (XMLDOMSchemaCollection) Adds all the schemas from another collection into the current collection.
get (namespaceURI) Returns a read-only DOM node containing the <Schema> element.
namespaceURI (index) Returns the namespace for the specified index.
remove (namespaceURI) Removes the specified namespace from the collection.

Now that we've examined the properties and methods in the IXMLDOMDocument2 interface and the IXMLDOMSchemaCollection interface, it's time to see how they are used in the application. Create a new Visual Basic Standard EXE project, and name the default form frmTestDOM2. In the form frmTestDOM2, place a command button with the name cmdSchemas and the caption Schemas. Place the following code in the click event handler of this button:

  Private Sub cmdSchemas_Click()
      Dim objXMLDoc As DOMDocument26
      Dim objXMLSchemas As XMLSchemaCache
      Dim lngSchemaCounter As Long
      Set objXMLDoc = New DOMDocument
      objXMLDoc.async = False
      objXMLDoc.Load ("c:\Books.xml")
      Set objXMLSchemas = objXMLDoc.namespaces
      For lngSchemaCounter = 0 To objXMLSchemas.length - 1
          Debug.Print "URL: " & _
              objXMLSchemas.namespaceURI(lngSchemaCounter)
          Debug.Print "Type: " & _
              objXMLDoc.selectSingleNode("//author").dataType
      Next
      Set objXMLSchemas = Nothing
      Set objXMLDoc = Nothing
  End Sub

This application loads the Books.xml document that contains a reference to the Books.dtd. If you run this program and click the Schemas button when the XML document is referencing the DTD, you will get the following result:

  URL: www.northwindtraders.com/PO
  Type:

Looking back at the original XML document, you have the following two lines of code:

  <!DOCTYPE northwind:BOOKS SYSTEM "c:\Books.dtd">
  <northwind:BOOKS xmlns: northwind ="www.northwind.com/PO">

You can see that the !DOCTYPE declaration defined the location of the DTD. Because XML documents are aware of namespaces, the parser recognized that the prefix northwind was a namespace prefix for the BOOKS element. In the next line of code, the parser finds the declaration that associates a namespace with that name and with that declaration. There is no data type information in the result above because this is a DTD.

We will now use a BizTalk schema instead of a DTD. Create the following schema file called Books.xsd:

  <Schema name="BOOKS" xmlns="urn:schemas-microsoft-com:xml-data"
     xmlns:dt="urn:schemas-microsoft-com:datatypes">
     <ElementType name="BOOKS" content="eltOnly" model="closed">
        <element type="item"/>
     </ElementType>
     <ElementType name=" item" content="eltOnly" model="closed">
        <element type="title"/>
        <element type="author"/>
        <element type="price"/>
        <element type="quantity"/>
     </ElementType>
     <ElementType name="title" content="mixed" model="closed">
        <AttributeType name="language" dt:type="string"/>
        <attribute type="language"/>
     </ElementType>
     <ElementType name="author" content="textOnly" model="closed"
        dt:type="string"/>
     <ElementType name="price" content="textOnly" model="closed"
        dt:type="string"/>
     <ElementType name="quantity" content="textOnly" model="closed"
        dt:type="string"/>
  </Schema>

Create a new XML document called Books2.xml and add the following code:

  <?xml version="1.0" ?>
  <northwind:BOOKS xmlns:northwind="x-schema:c:\Books.xsd">
     <northwind:item>
        <northwind:title language="English">Number, the
              Language of Science</northwind:title>
        <northwind:author>Danzig</northwind:author>
        <northwind:price>5.95</northwind:price>
        <northwind:quantity>3</northwind:quantity>
     </northwind:item>
  </northwind:BOOKS>

Notice that to get a reference to the schema we must use x-schema in the namespace declaration. The x-schema syntax is used by Internet Explorer 5 to identify where the schema is. The namespace prefix had to be added to all the elements in order for this code to work. While that should not have been necessary, errors would result if the namespace prefix was not added. This is a reminder that the way things are implemented might not always be what you expect. Finally, change the Visual Basic code so that it references Books2.xml and the namespace prefix is included in the XSL statement:

  Private Sub cmdSchemas_Click()
      Dim objXMLDoc As DOMDocument26
      Dim objXMLSchemas As XMLSchemaCache
      Dim lngSchemaCounter As Long
      Set objXMLDoc = New DOMDocument
      objXMLDoc.async = False
      objXMLDoc.Load ("c:\Books2.xml")
      Set objXMLSchemas = objXMLDoc.namespaces
      For lngSchemaCounter = 0 To objXMLSchemas.length - 1
          Debug.Print "URL: " & _
               objXMLSchemas.namespaceURI(lngSchemaCounter)
          Debug.Print "Type: " & objXMLDoc.selectSingleNode & _
               ("//northwind:author").dataType
      Next
  End Sub

After you make the changes, running the program and clicking the Schemas button will result in the following output:

  URL: x-schema:c:\Books.xsd
  Type: string

As you can see, we get the data type information this time because the schema contains the data type information.

The XMLDOMSelection object represents a list of nodes that match an XSL pattern or an XPath expression. The XMLDOMSelection object can be created by using the selectNodes method of the IXMLDOMDocument2 interface that is included in version 2.6 and later of Microsoft XML parser. This object implements the IXMLDOMSelection interface, which inherits from the IXMLDOMNodeList interface. In Visual Basic, the XMLDOMSelection object can be used as follows:

  Dim objXMLDoc As DOMDocument26
  Dim objXMLSelection As IXMLDOMSelection
  Set objXMLDoc = New DOMDocument26
  objXMLDoc.async = False
  objXMLDoc.Load ("C:\Books.xml")
  Set objXMLSelection = objXMLDoc.selectNodes("//item [quantity=3]")
  Debug.Print objXMLSelection.expr

In this example, we select the item element that has an attribute with a value of 3. The expr property of IXMLDOMSelection is used to retrieve the XPath expression string. In this case, "//item [quantity=3]" is returned.

Summary

In this chapter, you reviewed the majority of the XML DOM objects. These objects allow you to manipulate an XML document in virtually any way that might be required by an application. These objects provide a powerful set of tools that allow you to begin building complete XML applications. You can also use the DOM objects to both send messages to and receive messages from a Web server, which allows you to create SOAP messages as shown in the example in this chapter. In the next chapter, we will look at XSL and learn how the DOM can be used with it.