VBチームのブログの言わんとするところは次のようなことではないかと考えられます.
2.このクラスを継承した目的の処理を実装するクラスを作る.特別な処理をしたい要素はオーバーライド関数を追加する.
VBチームの作ってくれた1のコードは以下のようなものです.
Imports Microsoft.VisualBasic
Public MustInherit Class VBXmlTransform
Public Overridable Function Transform(ByVal xmlDoc As XDocument) As XDocument
<%= ProcessElement(xmlDoc.Root) %>
End Function
Public Overridable Function ProcessNode(ByVal xmlNode As XNode) As XNode
' This method ignores DTD (XDocumentType) content.
Dim nodeType = xmlNode.GetType()
' Because XCData inherits from XText, check for the XCData type before checking
' for XText.
If nodeType Is GetType(XCData) Then Return ProcessCData(xmlNode)
If nodeType Is GetType(XText) Then Return ProcessText(xmlNode)
If nodeType Is GetType(XElement) Then Return ProcessElement(xmlNode)
If nodeType Is GetType(XComment) Then Return ProcessComment(xmlNode)
If nodeType Is GetType(XProcessingInstruction) Then Return _
ProcessProcessingInstruction(xmlNode)
Return xmlNode
End Function
Public Overridable Function ProcessAttribute(ByVal xmlAttribute As XAttribute) As XAttribute
Return xmlAttribute
End Function
Public Overridable Function ProcessCData(ByVal xmlCData As XCData) As XCData
Return xmlCData
End Function
Public Overridable Function ProcessText(ByVal xmlText As XText) As XText
Return xmlText
End Function
Protected Overridable Function ProcessComment(ByVal xmlComment As XComment) As XComment
Return xmlComment
End Function
Public Overridable Function ProcessProcessingInstruction( _
ByVal pi As XProcessingInstruction) As XProcessingInstruction
Return pi
End Function
Public Overridable Function ProcessElement(ByVal xmlElement As XElement) As XElement
Return CopyElement(xmlElement)
End Function
Public Overridable Function CopyElement(ByVal xmlElement As XElement) As XElement
Return <<%= xmlElement.Name %>
<%= From attribute In xmlElement.Attributes() _
Select ProcessAttribute(attribute) %>>
<%= From node In xmlElement.Nodes() _
Select ProcessNode(node) %>
</>
End Function
End Class
そして2のサンプルは以下のようなものです.
Imports Microsoft.VisualBasic
Imports <xmlns="">http://SampleSchema/AWContacts">
Imports <xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo">
Imports <xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
Public Class AWTransform
Inherits VBXmlTransform
' Rename <act:PostalCode> to <ZipCode>.
'
' Create an XName object to use for comparisons. This will perform better than comparing
' xmlElement.Name.LocalName to a string.
Private postalCodeXName As XName = _
XName.Get("PostalCode", _
Public Overrides Function ProcessElement(ByVal xmlElement As XElement) As XElement
Select Case xmlElement.Name
Case postalCodeXName
Return TransformPostalCode(xmlElement)
Case Else
Return MyBase.ProcessElement(xmlElement)
End Select
Return Nothing
End Function
Public Function TransformPostalCode(ByVal postalCodeElement As XElement) As XElement
Return <ZipCode><%= postalCodeElement.Value %></ZipCode>
End Function
End Class
コメントにあるように、<act:PostalCode> を <ZipCode>に置換します.ここで一番大切なところは、赤字で示した条件分岐です.もし本格的にXSLTコンパチブルなコードを書こうと思ったら、この箇所にすべての処理したい要素の条件を記述し、すべての変換関数を実装しなければなりません.
Case postalCodeXName
Return TransformPostalCode(xmlElement)
は、ネームスペースプレフィックスactをhttp://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypesにスタイルシートの先頭でマッピングさせて
<xsl:template match="act:PostalCode">
<ZipCode>
<xsl:value-of select="string(.)"/>
</ZipCode>
</xsl:template>
と書くのと等価です.
また
Case Else
Return MyBase.ProcessElement(xmlElement)
は
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
と等価です.
また、XSLTテンプレートなら
<xsl:template match="パターン">
と書けます.特定の要素にマッチさせたいなら、例えば
match="acme:someElem[制約条件]"
と簡単に記述できます.でもVBでは条件分岐を全部記述して目的の関数を呼び出さねばなりません.
このような処理を一般のプログラミング言語でもなるべく簡単にかける仕組みはないものでしょうか?