VBチームのブログ(1)

以前紹介しましたが、MicrosoftVisual Basicの開発チームのブログに、VBXMLを処理する一連のトピックが載っています.ファイルをコピーする、XSLTと同じような変換処理を記述するというサンプルもあり、なかなかおもしろく読めます.

VB XML Cookbook

もう2008年にかかれたものですけれど、これを見て「.NETプラットフォームでXSLTは終焉を迎える?」なんて大仰なことを書いたInfoQの記事もありました.(⇒もちろん2013年の今もXSLTVBに取って代わられる事態にはなっていませんが...)

The End of XSLT for .NET Programmers?

さてこの6番目の記事にXMLをコピーする例があります.

VB XML Cookbook, Recipe 6: Writing an XSLT Transform in VB (Doug Rothaus)

この中でXMLファイルをコピーする例があるのですが、私が以前書いたものとは違い、XMLリテラルを効果的に使っています.

[私の以前のコード]⇒ http://blogs.yahoo.co.jp/tnakita/14656952.html

Function ProcessNode(node As XNode) As XNode
  Select Case node.NodeType
    Case XmlNodeType.Element
        Dim elem As XElement = DirectCast(node, XElement)
        Dim newElem As XElement = New XElement(elem.Name)
        newElem.Add(elem.Attributes)
        Dim childNode As IEnumerable(Of XNode) = elem.Nodes
        For Each node In childNode
            Dim newNode As XNode = ProcessNode(node)
            newElem.Add(newNode)
        Next
        Return newElem
    Case XmlNodeType.Text
        Dim text As XText = DirectCast(node, XText)
        Dim newText As XText = New XText(text.Value)
        Return newText
    Case XmlNodeType.Whitespace
        Dim text As XText = DirectCast(node, XText)
        Dim newText As XText = New XText(text.Value)
        Return newText
    Case Else
        Return Nothing
  End Select
End Function

問題は要素の処理です.VBチームのブログを参考に書き直すと以下のようになります.

XMLリテラルを使ったコード]

Function ProcessNode(node As XNode) As XNode
  Select Case node.NodeType
    Case XmlNodeType.Element
        Dim elem As XElement = DirectCast(node, XElement)
        Return <<%= elem.Name %>
                   <%= From attribute In elem.Attributes() _
                       Select attribute %>>
                   <%= From childNode In elem.Nodes() _
                       Select ProcessNode(childNode) %>
               </>
    Case XmlNodeType.Text
        Dim text As XText = DirectCast(node, XText)
        Dim newText As XText = New XText(text.Value)
        Return newText
    Case XmlNodeType.Whitespace
        Dim text As XText = DirectCast(node, XText)
        Dim newText As XText = New XText(text.Value)
        Return newText
    Case Else
        Return Nothing
  End Select
End Function

VBではXMLリテラルの中に、<%= expression %> と書いて、式を埋め込めてしまいます.

<%= elem.Name %> 

と書いて要素名を取得して埋め込めて、

<%= From childNode In elem.Nodes() _
    Select ProcessNode(childNode) %>

LINQクェリーも埋め込めてしまいます.非常に直感的にXMLリテラルの中に式を使って結果を生成できるのには正直驚きます.

このようなXMLリテラルが使えるのがVisual Studioの言語のなかでもVBのみというのは、Microsoftの並々ならぬ思い入れを感じさせずにはおられません.

次は、このブログのなかで紹介されているXSLTを模したコードについて書きたいと思います.