読者です 読者をやめる 読者になる 読者になる

VB.NETでもXMLを扱いたい(その2)

前回までのあらすじ

軽くXMLとかXPathとかを記事にしてめっきり減った投稿間隔を少しでも上げようと画策した弊社であるが、20行程度のXMLから80行ものXMLスキーマが生成され紹介するだけで8500文字にも及ぶ内容の薄い記事が出来上がり『こんなはずじゃ・・・』と一人頭を抱えた15の夜を過ごしている弊社だった。

嘘です。15歳じゃないです。永遠の17歳です。

XMLスキーマの読み込み

今回は前回無駄に文字数を増やしたXMLスキーマをファイルから読み込み表示させてみましょう。

Module Module1

    Sub Main()
        Section1()
    End Sub

    Function ReadSchema() As XmlSchema
        Dim xs As XmlSchema
        Using r = New StreamReader("mailbox.xsd")
            xs = XmlSchema.Read(r, Sub(sender, e) Console.WriteLine("{0}:{1}", e.Severity, e.Message))
        End Using
        Return xs
    End Function

    Sub Section1()
        Dim xs = ReadSchema()
        TraverseXmlSchemaElement(xs, 0)
    End Sub

    Sub TraverseXmlSchemaElement(node As XmlSchemaObject, level As Integer)
        If TypeOf node Is XmlSchema Then
            Dim it = DirectCast(node, XmlSchema)
            Console.WriteLine("{0}XmlSchema", Indent(level))
            For Each i In it.Items
                TraverseXmlSchemaElement(i, level + 1)
            Next
        ElseIf TypeOf node Is XmlSchemaElement Then
            Dim it = DirectCast(node, XmlSchemaElement)
            If Not String.IsNullOrWhiteSpace(it.Name) Then
                Console.WriteLine("{0}XmlSchemaElement:{1}", Indent(level), it.Name)
            Else
                Console.WriteLine("{0}XmlSchemaElement:RefName:{1}", Indent(level), it.RefName.Name)
            End If

            If TypeOf it.SchemaType Is XmlSchemaComplexType Then
                Dim j = DirectCast(it.SchemaType, XmlSchemaComplexType)
                For Each k In j.Attributes
                    TraverseXmlSchemaElement(k, level + 1)
                Next
                TraverseComplexType(j.Particle, level + 1)
            End If
        ElseIf TypeOf node Is XmlSchemaAttributeGroup Then
            Dim it = DirectCast(node, XmlSchemaAttributeGroup)
            Console.WriteLine("{0}XmlSchemaAttributeGroup:{1}", Indent(level), it.Name)
            For Each i In it.Attributes
                TraverseXmlSchemaElement(i, level + 1)
            Next
        ElseIf TypeOf node Is XmlSchemaAttributeGroupRef Then
            Dim it = DirectCast(node, XmlSchemaAttributeGroupRef)
            Console.WriteLine("{0}XmlSchemaAttributeGroupRef:{1}", Indent(level), it.RefName.Name)
        ElseIf TypeOf node Is XmlSchemaAttribute Then
            Dim it = DirectCast(node, XmlSchemaAttribute)
            Console.WriteLine("{0}XmlSchemaAttribute:{1}", Indent(level), it.Name)
        End If
    End Sub

    Sub TraverseComplexType(particle As XmlSchemaParticle, level As Integer)
        If TypeOf particle Is XmlSchemaGroupBase Then
            Dim it = DirectCast(particle, XmlSchemaGroupBase)
            Console.WriteLine("{0}{1}", Indent(level), it.GetType.Name)
            For Each i In it.Items
                TraverseXmlSchemaElement(i, level + 1)
            Next
        Else
            If Not particle Is Nothing Then
                Console.WriteLine("{0}{1}", Indent(level), particle.GetType.Name)
            End If
        End If
    End Sub

    Function Indent(level As Integer) As String
        Dim s = ""
        For i = 1 To level
            s = s + "    "
        Next
        Return s
    End Function

End Module
XmlSchema
    XmlSchemaElement:mailbox
        XmlSchemaSequence
            XmlSchemaElement:RefName:mail
    XmlSchemaElement:mail
        XmlSchemaSequence
            XmlSchemaElement:RefName:from
            XmlSchemaElement:RefName:recipient
            XmlSchemaElement:RefName:subject
            XmlSchemaElement:RefName:body
    XmlSchemaAttributeGroup:mailAddress
        XmlSchemaAttribute:name
        XmlSchemaAttribute:address
    XmlSchemaElement:from
        XmlSchemaAttributeGroupRef:mailAddress
    XmlSchemaElement:recipient
        XmlSchemaSequence
            XmlSchemaElement:RefName:to
            XmlSchemaElement:RefName:cc
            XmlSchemaElement:RefName:bcc
    XmlSchemaElement:to
        XmlSchemaAttributeGroupRef:mailAddress
    XmlSchemaElement:cc
        XmlSchemaAttributeGroupRef:mailAddress
    XmlSchemaElement:bcc
        XmlSchemaAttributeGroupRef:mailAddress
    XmlSchemaElement:subject
        XmlSchemaChoice
            XmlSchemaElement:text
            XmlSchemaElement:RefName:file
    XmlSchemaElement:body
        XmlSchemaChoice
            XmlSchemaElement:text
            XmlSchemaElement:RefName:file
    XmlSchemaElement:file
        XmlSchemaAttribute:path

と言っても、別にxsdファイルで検証を行うだけならこんなことしなくてもいいんですけどね。 まぁ、こんな感じにXMLスキーマをプログラム中からも参照したり変更したりできるってことで。

XmlSchemaElement クラス (System.Xml.Schema)

おわり