Back Contents Next

The C_XML Class

The C_XML class is responsible for formatting the XML string that is returned when a calling application requests the XML data format. It has a single public method (BuildXML) that formats the XML for a given Recordset object. The C_XML class is only used if XML was requested by the calling application.

 

Property

Setting

Reasoning

Instancing

MultiUse

This class will be instantiated in our DLL running under MTS.

MTSTransactionMode

NoTransactions

We don't want to join any MTS transactions initiated by the calling program. This object doesn't interact with an underlying data source, so there is no need to have it join a transaction.

Class Level Declarations

In the following code section, we define a constant that holds the name of our class. Next, since we want to build our code to run under MTS, we implement the ObjectControl interface and all of its methods. As in the C_Data_ADO_MTS class, this gives MTS a way to tell us when the class is activated and deactivated under MTS.

 

Then we create a private Type that holds all of our class level variables. This time we have two class level variables: oObjCtx and oXML. We discussed the purpose of the oObjCtx object when we examined the C_Data_ADO_MTS class. The oXML object variable, however, is new to our code. This variable references an instance of the MSXML.DOMDocument object library. We'll use the library to generate XML, based on the Recordset we pass in to this class' BuildXML method (shown in the next section).

 

Option Explicit

 

'------------------------------------------------------------------------------

'--- *** You may use this code as long as you keep these comments in place. ***

'--- ORIGINALLY WRITTEN BY: Blue Sand Software, Inc.

'--- DATE WRITTEN: December 1999

'---

'------------------------------------------------------------------------------

'--- Name of this object

Private Const msOBJ_NAME As String = "C_XML"

 

'--- MTS Object control interface

Implements ObjectControl

 

Private Type typeThis

    oObjCtx As ObjectContext '--- MTS Object context

    oXML As MSXML.DOMDocument '--- XML Document Object

End Type

 

Private m As typeThis

The BuildXML Method

The BuildXML method is the only public interface for the C_XML class. It accepts an ADO Recordset object and builds an XML document using the MSXML object library. This method is quite lengthy, but I tried to comment it well enough so that you can follow it line by line.

 

It starts out by creating the metadata nodes in the XML stream. To create this part of the XML, we loop through the Fields collection of the Recordset and add each Field and its attributes to the XML stream:

 

Public Function BuildXML(ByVal oRs As Recordset) As String

'--- Build XML from the data and metadata

  Const sPROC_NAME As String = msOBJ_NAME & ".BuildXML"

  Const lMetaDataTag As Long = 0

  Const lMetaDataFieldsTag As Long = 0

  Const lDataTag As Long = 1

  Const lDataRowsTag As Long = 0

  Const lDataRowsRowFieldsTag As Long = 0

 

  Dim lRow As Long

  Dim lCol As Long

  Dim sXML As String

 

  If oRs.EOF And oRs.BOF Then Exit Function

 

  '--- Create XML document element

  Set m.oXML.documentElement = m.oXML.createElement("xml")

 

  '--- With <xml>

  With m.oXML.documentElement

 

  '-------------------------------------------------------

  '--- CREATE METADATA

  '-------------------------------------------------------

  '--- Create MetaData node

    .appendChild CreateNode("metadata")

 

  '--- Create MetaData Fields node

    .childNodes(lMetaDataTag).appendChild CreateNode("fields")

 

  '--- With <fields>

    With .childNodes(lMetaDataTag).childNodes(lMetaDataFieldsTag)

 

  '--- Loop through Recordset fields to

  '--- create MetaData Field nodes

      For lCol = 0 To oRs.Fields.Count - 1

                '--- Create the Field node

        .appendChild CreateNode("field")

 

  '--- Create all of the metadata attributes

  '--- With <field> attributes

        With .childNodes(lCol).Attributes

 

  '--- Create Index attribute

          .setNamedItem CreateAttribute("Index", lCol)

 

  '--- Create Name attribute

          .setNamedItem CreateAttribute("Name", oRs.Fields(lCol).Name)

 

  '--- Create Type attribute

          .setNamedItem CreateAttribute("Type", oRs.Fields(lCol).Type)

 

  '--- Create DefinedSize attribute

          .setNamedItem CreateAttribute("DefinedSize", oRs.Fields(lCol).DefinedSize)

 

  '--- Create NumericScale attribute

          .setNamedItem CreateAttribute("NumericScale", oRs.Fields(lCol).NumericScale)

 

  '--- Create Precision attribute

          .setNamedItem CreateAttribute("Precision", oRs.Fields(lCol).Precision)

 

  '--- Create IsIdentity attribute

          .setNamedItem CreateAttribute("IsIdentity", _
                        IIf(oRs.Fields(lCol).Properties.Item("ISAUTOINCREMENT"), _
                         "True", "False"))

 

  '--- Create IsNullable attribute

          .setNamedItem CreateAttribute("IsNullable", _
                          IIf(CBool(oRs.Fields(lCol).Attributes And _
                            adFldIsNullable), "True", "False"))

 

  '--- Create Updateable attribute

          .setNamedItem CreateAttribute("Updateable", _
                          IIf(CBool(oRs.Fields(lCol).Attributes And _
                            adFldUnknownUpdatable), "True", "False"))

 

  '--- Create FixedLength attribute

          .setNamedItem CreateAttribute("FixedLength", _
                          IIf(CBool(oRs.Fields(lCol).Attributes And adFldFixed), _
                            "True", "False"))

 

  '--- Create LongBinary attribute

          .setNamedItem CreateAttribute("LongBinary", _
                          IIf(CBool(oRs.Fields(lCol).Attributes And adFldLong), _
                            "True", "False"))

 

  '--- Create PrimaryKey attribute

          .setNamedItem CreateAttribute("PrimaryKey", _
                          IIf(oRs.Fields(lCol).Properties.Item("KEYCOLUMN"), _

                            "True", "False"))

        End With

      Next

    End With

 

  '-------------------------------------------------------

  '--- CREATE DATA

  '-------------------------------------------------------

 

  '--- Create Data node

    .appendChild CreateNode("data")

 

  '--- Create Data Rows node

    .childNodes(lDataTag).appendChild CreateNode("rows")

 

    oRs.MoveFirst

 

  '--- With <rows>

      With .childNodes(lDataTag).childNodes(lDataRowsTag)

        Do While Not oRs.EOF

          lRow = oRs.AbsolutePosition - 1

               

  '--- Create the Row node

          .appendChild CreateNode("row")

 

  '--- Create Index attribute

          .childNodes(lRow).Attributes.setNamedItem CreateAttribute("Index", lRow)

 

  '--- Create the Fields node

          .childNodes(lRow).appendChild CreateNode("fields")

               

                '--- With <fields>

          With .childNodes(lRow).childNodes(lDataRowsRowFieldsTag)

 

  '--- Loop through Recordset fields to

  '--- create Data Field nodes

 

            For lCol = 0 To oRs.Fields.Count - 1

                       

  '--- Create the Field node

              .appendChild CreateNode("field")

 

  '--- With <field>

              With .childNodes(lCol)

 

  '--- Create Index attribute

                .Attributes.setNamedItem CreateAttribute("Index", lCol)

 

 '--- Create Name attribute

                .Attributes.setNamedItem CreateAttribute("Name", _
                            oRs.Fields(lCol).Name)

 

  '--- Create Field Data

                .Text = oRs.Fields(lCol).Value

              End With

            Next

          End With

          oRs.MoveNext

        Loop

      End With

    End With

   

    sXML = m.oXML.xml

   

    Set oRs = Nothing

   

    BuildXML = sXML

 

  '----------------------------------------------------------------

  '--- Complete the MTS Transaction

  '----------------------------------------------------------------

    Set m.oXML = Nothing

    m.oObjCtx.SetComplete

           

  Exit Function

  Err:

 

  '----------------------------------------------------------------

  '--- Abort the MTS Transaction

  '----------------------------------------------------------------

    Dim sError As String: sError = Err.Description

    Dim sSource As String: sSource = Err.Source

    Dim lErrNum As Long: lErrNum = Err.Number

    On Error Resume Next

 

  '----------------------------------------------------------------

  '--- Cleanup

  '----------------------------------------------------------------

    Set oRs = Nothing

   

    '----------------------------------------------------------------

    '--- Abort the transaction

    '----------------------------------------------------------------

    m.oObjCtx.SetAbort

 

    On Error GoTo 0

    Err.Raise lErrNum, sSource & " <--- " & sPROC_NAME, sError

  End Function

 

Then we get to the code that generates the data nodes (CreateNode and CreateAttribute) in the XML stream. To create this part of the XML, we loop through the rows of data in the Recordset. Then, for each row node, we loop through the Fields collection of the Recordset and add each Field and its value to the XML stream. In the end, we have a string of XML that we pass back to the C_Data_ADO_MTS class' ExecuteSQL method and, from there, back to the calling application. Once there, we can use the XML to display the data in Internet Explorer or we can pass it to another application for processing.

The CreateNode Private Method

This method is simply used to abstract the creation of XML element nodes (i.e. <fields> or <rows>):

 

Private Function CreateNode(ByVal sName As String) As MSXML.IXMLDOMNode

    Set CreateNode = m.oXML.CreateNode(NODE_ELEMENT, sName, "")

End Function

The CreateAttribute Private Method

This method is simply used to abstract the creation of XML element attribute nodes. In other words, we use this function to define an attribute and its value on a given XML element. For example, we could use this function to define the Index attribute of a <field> tag to result in: <field Index="7">.

 

Private Function CreateAttribute(ByVal sName As String, _

                 ByVal vValue As Variant) As MSXML.IXMLDOMNode

    Dim oXMLNode As MSXML.IXMLDOMNode

   

    Set oXMLNode = m.oXML.CreateNode(NODE_ATTRIBUTE, sName, "")

    oXMLNode.nodeTypedValue = vValue

    Set CreateAttribute = oXMLNode

End Function

The ObjectControl Interface

Again, since we are integrating this class with MTS and have declared that we intend to implement the ObjectControl interface, we must implement all of the methods of the interface (shown in the following code section). The ObjectControl_Activate method is invoked by MTS when a calling application requests a C_XML object and the ObjectControl_Deactivate method is invoked by MTS when a calling application is finished with the instance of the object.

 

In the ObjectControl_Activate method, we also create an instance of the MSXML.DOMDocument object. We'll be using the object throughout this class as we generate the XML document, so it will be handy to keep it around during the life of this object.

 

Private Sub ObjectControl_Activate()

    On Error GoTo 0

   

    If m.oObjCtx Is Nothing Then

        Set m.oObjCtx = GetObjectContext()

        Set m.oXML = CreateObject("MSXML.DOMDocument")

    End If

End Sub

 

Private Function ObjectControl_CanBePooled() As Boolean

  ObjectControl_CanBePooled = True

End Function

 

Private Sub ObjectControl_Deactivate()

    On Error GoTo 0

   

    '--- Clean up

    Set m.oObjCtx = Nothing

    Set m.oXML = Nothing

 


Back Contents Next
©1999 Wrox Press Limited, US and UK.