Uncommented Code for the Walk the SOM Application

 

[This sample code uses features that were only implemented in MSXML 6.0.]

' Item types:
Option Explicit
Const SOMITEM_SCHEMA                    = 4*1024
Const SOMITEM_ATTRIBUTE                 = SOMITEM_SCHEMA + 1
Const SOMITEM_ATTRIBUTEGROUP            = SOMITEM_SCHEMA + 2
Const SOMITEM_NOTATION                  = SOMITEM_SCHEMA + 3

Const SOMITEM_ANYTYPE                   = 8*1024
Const SOMITEM_DATATYPE                  = SOMITEM_ANYTYPE+256
Const SOMITEM_SIMPLETYPE                = SOMITEM_DATATYPE+256
Const SOMITEM_COMPLEXTYPE               = 9*1024

Const SOMITEM_PARTICLE                  = 16*1024
Const SOMITEM_ANY                       = SOMITEM_PARTICLE+1
Const SOMITEM_ANYATTRIBUTE              = SOMITEM_PARTICLE+2
Const SOMITEM_ELEMENT                   = SOMITEM_PARTICLE+3
Const SOMITEM_GROUP                     = SOMITEM_PARTICLE+256

Const SOMITEM_ALL                       = SOMITEM_GROUP+1
Const SOMITEM_CHOICE                    = SOMITEM_GROUP+2
Const SOMITEM_SEQUENCE                  = SOMITEM_GROUP+3
Const SOMITEM_EMPTYPARTICLE             = SOMITEM_GROUP+4

' Attribute uses
Const SCHEMAUSE_OPTIONAL   = 0
Const SCHEMAUSE_PROHIBITED = 1
Const SCHEMAUSE_REQUIRED   = 2

Const SCHEMACONTENTTYPE_EMPTY        = 0
Const SCHEMACONTENTTYPE_TEXTONLY     = 1
Const SCHEMACONTENTTYPE_ELEMENTONLY  = 2
Const SCHEMACONTENTTYPE_MIXED        = 3

Public result As String
Public t As Integer
Dim remarks
Private Sub form_load()
Dim nsTarget As String
Dim oSchema As ISchema
Dim oSchemaCache As New XMLSchemaCache60
Dim oAnnotationDoc As New DOMDocument60
Dim oE As ISchemaElement
Dim oA As ISchemaAttribute
Dim oT As ISchemaType

remarks = 1

Set oSchemaCache = CreateObject("Msxml2.XMLSchemaCache.6.0")
Set oAnnotationDoc = CreateObject("Msxml2.DOMDocument.6.0")

' Load the schema.
nsTarget="http://www.example.microsoft.com/po"

oSchemaCache.add nsTarget, "po.xsd"
Set oSchema = oSchemaCache.getSchema(nsTarget)

result = "<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"+ vbNewLine

For Each oE in oSchema.elements
    result = result + printElement(oE, 0)
Next

For Each oA in oSchema.attributes
    result = result + printAttr(oA, t)
Next

result = result + vbNewLine

For Each oT in oSchema.types
    result = result + processType(oT, 0)
Next

result = result + "</xsd:schema>"

Text1.Text = result
End Sub

' -------------------------------------------------------------------------------------------
Function processType(oType, t)
     Dim res As String
'    res = printTab(t) + printRemark(oType.name)+ vbNewLine
    If oType.itemType = SOMITEM_ANYTYPE Then
        res = res + printTab(t+1) + "<!-- " + oType.name +" -->" 
    End If
    If oType.itemType = SOMITEM_COMPLEXTYPE Then
        res = res + processComplexType(oType, t+1)
    End If
    If oType.itemType = SOMITEM_SIMPLETYPE Then
        res = res + processSimpleType(oType, t+1)
    End If
    processType = res + vbNewLine
End Function

Function processComplexType(oComplex, t)
    Dim res As String
    Dim strAny As String
    Dim oAttr As ISchemaAttribute

    res = printTab(t) + "<xsd:complexType"
    If oComplex.name <> "" Then
        res = res + " name='" + oComplex.name +"'"
    End If
    res = res + ">"

    If oComplex.contentType = SCHEMACONTENTTYPE_EMPTY Then
        res = res + printRemark("emtpy")
    End If
    If oComplex.contentType = SCHEMACONTENTTYPE_TEXTONLY Then
        res = res + printRemark("textonly")
    End If
    If oComplex.contentType =SCHEMACONTENTTYPE_ELEMENTONLY Then
        res = res + printRemark("elementonly")
        res = res + processGroup(oComplex.contentModel, t+1)
    End If
    If oComplex.contentType = SCHEMACONTENTTYPE_MIXED Then
        res = res + printRemark("mixed")
        res = res + processGroup(oComplex.contentModel, t+1)
    End If
    res = res + vbNewline
    If oComplex.baseTypes.length > 0 Then
        res = res + printRestrictions(oComplex, t+1)
    End If
    On Error Resume Next
    StrAny = oComplex.anyAttribute.name
    If Err.number = 0 Then
        res = res + oComplex.anyAttribute.name
    End If

    For Each oAttr in oComplex.attributes
        res = res + printAttr(oAttr, t+1)
    Next

    processComplexType = res + printTab(t) + "</xsd:complexType>"+vbNewline
End Function

Function processSimpleType(oSimple, t)
    Dim res As String
    Dim oType As ISchemaType

    res = printTab(t) + "<xsd:simpleType"
    If oSimple.name <> "" Then
        res = res + " name='" + oSimple.name +"'"
    End If
    res = res + ">"+vbNewline

    If oSimple.baseTypes.length = 1 Then
        res = res + printRestrictions(oSimple, t+1)
    Else
        For Each oType in oSimple.baseTypes
            res = res + "<baseType name='" + printName(oType) +"'>"+vbNewline
        Next
    End If

    processSimpleType = res + printTab(t) + "</xsd:simpleType>"+vbNewline
End Function

Function processGroup(poGroup, t)
    Dim res As String
    res = ""
    ' List elements in the sequence.

    If poGroup.itemType = SOMITEM_ALL Then
        res = res + printTab(t+1) + "<xsd:all>"+vbNewline
        res = res + processChoiceOrSequence(poGroup, t+1)
        res = res + printTab(t+1) + "</xsd:all>"
    End If

    If poGroup.itemType = SOMITEM_CHOICE Then
        res = res + printTab(t+1) + "<xsd:choice>"+vbNewline
        res = res + processChoiceOrSequence(poGroup, t+1)
        res = res + printTab(t+1) + "</xsd:choice>"
    End If

    If poGroup.itemType = SOMITEM_SEQUENCE Then
        res = res + printTab(t+1) + "<xsd:sequence>"+vbNewline
        res = res + processChoiceOrSequence(poGroup, t+1)
        res = res + printTab(t+1) + "</xsd:sequence>"
    End If
    processGroup = res
End Function

Function processChoiceOrSequence(poGroup, t)
    Dim res As String
    Dim item As ISchemaParticle

    res = ""
    For Each item in poGroup.particles
        If item.itemType = SOMITEM_ELEMENT Then
            res = res + printElement(item, t+1)
        End If
        If (item.itemType and SOMITEM_GROUP) = SOMITEM_GROUP Then
            res = res + processGroup(item, t+1)+vbNewline
        End If
        If item.itemType = SOMITEM_ANY Then
            res = res + "any: " + item.name+vbNewline
        End If
    Next
    processChoiceOrSequence = res
End Function

Function printElement(oElement, t)
    Dim res As String
    Dim strRem As String
    Dim oType As ISchemaType

    res = printTab(t) + "<xsd:element "
    If oElement.isReference Then
        res = res + "ref='" + oElement.name + "'" + printParticles(oElement) + ">"
        res = res + "<!-- "
        res = res + " abstract='" & oElement.isAbstract & "'"
        res = res + " -->"
    Else
        Set oType=oElement.type
        res = res + "name='" + oElement.name + "'" + printParticles(oElement)
        res = res + " abstract='" & oElement.isAbstract & "'"
        res = res + " id='" & oElement.id & "'"
        If oType.name = "" Then
            res = res + ">" + vbNewLine 
            If oType.itemType = SOMITEM_COMPLEXTYPE Then
                res = res + printElement + processComplexType(oType, t+1)
            Else
                res = res + processSimpleType(oType, t)
            End If
            res = res + printTab(t) + "</xsd:element>"
        Else
            If printName(oType) <> "xsd:anyType" Then
                res = res + " type='" + printName(oType) + "'"
            End If

            If oType.itemType <> SOMITEM_COMPLEXTYPE Then
                If oType.baseTypes.length = 0 Then
                    res = res + "/>"
                Else
                    res = res + ">" + vbNewLine + processSimpleType(oType, t)
                    res = res + printTab(t) + "</xsd:element>"
                End If
            Else
                res = res + "/>"
            End If
        End If
    End If
    If Not oElement.scope Is Nothing Then
       strRem = "scope:" + printName(oElement.scope)
    End If
    res = res + printRemark(strRem)
    printElement = res
End Function

Function printParticles(oParticle)
    Dim res As String
        If oParticle.minOccurs <> 1 Then 
            res = res + " minOccurs='" & oParticle.minOccurs & "'"
        End If
        If oParticle.maxOccurs <> 1 Then 
            If oParticle.maxOccurs = -1 Then 
                res = res + " maxOccurs='unbounded'"
            Else
                res = res + " maxOccurs='" & oParticle.maxOccurs & "'"
            End If
        End If
        printParticles = res
End Function

Function printAttr(oAttr, t)
        Dim strRem As String
        If oAttr.isReference Then
            printAttr = printAttr + printTab(t) + "<xsd:attribute ref='" + oAttr.name + "'"
        Else
            printAttr = printAttr + printTab(t) + "<xsd:attribute name='" + oAttr.name + "'"
        End If
        If oAttr.type.name <> "" Then
            printAttr = printAttr + " type='" + printName(oAttr.type) + "'"
        End If
        If oAttr.defaultValue <> "" Then
            printAttr = printAttr + " default='" + oAttr.defaultValue + "'"
        End If
        If oAttr.fixedValue <> "" Then
            printAttr = printAttr + " fixed='" + oAttr.fixedValue + "'"
        End If
        If oAttr.use = SCHEMAUSE_OPTIONAL   Then printAttr = printAttr + " use='optional'"
        If oAttr.use = SCHEMAUSE_PROHIBITED Then printAttr = printAttr + " use='prohibited'"
        If oAttr.use = SCHEMAUSE_REQUIRED   Then printAttr = printAttr + " use='required'"
        printAttr = printAttr + "/>"
        If Not oAttr.scope Is Nothing Then
           strRem = "scope:" + printName(oAttr.scope)
        End If
        printAttr = printAttr + printRemark(strRem)
End Function

Function printTab(t)
    Dim strTab As String
    Dim x As Integer

    strTab =""
    for x=0 to t
        strTab=strTab+"  "
    next
    printTab=strTab
End Function

Function printName(item)
    Dim res As String
    Dim item As ISchemaItem
    Dim opattern As Variant

    printName =""
    If (item.itemType and SOMITEM_DATATYPE) = SOMITEM_DATATYPE Then
        printName= "xsd:"
    End If 
    If item.itemType = SOMITEM_ANYTYPE Then
        printName= "xsd:"
    End If 
    printName= printName + item.name
End Function

Function printRestrictions(oType, t)
    Dim res As String
    Dim item As ISchemaItem
    Dim opattern As Variant

    res = ""
    If oType.minExclusive <> "" Then
        res = res + printTab(t+1) + "<xsd:minExclusive value='"+ oType.minExclusive + "'/>" + vbNewLine
    End If
    If oType.minInclusive <> "" Then
        res = res + printTab(t+1) + "<xsd:minInclusive value='"+ oType.minInclusive + "'/>" + vbNewLine
    End If
    If oType.maxExclusive <> "" Then
        res = res + printTab(t+1) + "<xsd:maxExclusive value='"+ oType.maxExclusive + "'/>" + vbNewLine
    End If
    If oType.maxInclusive <> "" Then
        res = res + printTab(t+1) + "<xsd:maxInclusive value='"+ oType.maxInclusive + "'/>" + vbNewLine
    End If
    If oType.totalDigits > -1 Then
        res = res + printTab(t+1) + "<xsd:totalDigits value='" & oType.totalDigits & "'/>" + vbNewLine
    End If
    If oType.fractionDigits > -1 Then
        res = res + printTab(t+1) + "<xsd:fractionDigits value='" & oType.fractionDigits & "'/>" + vbNewLine
    End If
    If oType.length > -1 Then
        res = res + printTab(t+1) + "<xsd:length value='" & oType.length & "'/>" + vbNewLine
    End If
    If oType.minLength > -1 Then
        res = res + printTab(t+1) + "<xsd:minLength value='" & oType.minLength & "'/>" + vbNewLine
    End If
    If oType.maxLength > -1 Then
        res = res + printTab(t+1) + "<xsd:maxLength value='" & oType.maxLength & "'/>" + vbNewLine
    End If
    If oType.enumeration.length > 0 Then
        For Each item in oType.enumeration
            res = res + printTab(t+1) + "<xsd:enumeration value='" + item + "'/>" + vbNewLine
        Next
    End If
    If oType.whitespace > 0 Then
        res = res + printTab(t+1) + "<xsd:whitespace value='" & oType.whitespace & "'/>" + vbNewLine
    End If
    If oType.patterns.length <> 0 Then
        For Each oPattern in oType.patterns
            res = res + printTab(t+1) + "<xsd:pattern value='" + opattern + "'/>" + vbNewLine
        Next
    End If

    printRestrictions = ""
    If res <> "" and oType.baseTypes.length > 0 Then
        printRestrictions = printRestrictions + printTab(t) + "<xsd:restriction base='" + printName(oType.baseTypes(0)) + "'>" + vbNewLine
        printRestrictions = printRestrictions + res
        printRestrictions = printRestrictions + printTab(t) + "</xsd:restriction>" + vbNewLine
    End If

End Function

Function printRemark(r)
    If remarks = 1 Then
        printRemark = "<!-- " + r + " -->"
    End If
    printRemark = printRemark + vbNewLine
End Function