[VB2008] XMLの読込とVB.NETについて

タグの編集
投稿者 tecc  (社会人) 投稿日時 2010/1/19 02:51:39
  VB.NET暦は浅いです

XMLファイルを作成しVB側で読込をしようと思っています。
考えている動作としては、[contents no="1"]を探して次に[contents no="1"]の
<q>と<anser>を取得したいです。
Public Sub SettingFile()
        Try
            Using xreder As XmlReader = _
                XmlReader.Create(_filepath)
                While xreder.Read
                    If xreder.ReadToFollowing("q"Then
                        questions = xreder.ReadElementString
                        anser = xreder.ReadElementString
                    End If
                End While
                'TODO リーダーを閉じる 
                xreder.Close()
            End Using
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString())
        End Try
    End Sub


手探りでこのようなコードを書きましたが、考えている動作が実行されません。
ReadToFollowingは[指定された修飾名の要素が見つかるまで読み込みます。]
との事なので、<q>要素を指定した所戻ってきた値はNothingでした。

<?xml version="1.0" encoding="Shift_JIS"?>
<question>
<contents no="1">
<q>Aさんの好きな食べ物は?</q>
<anser>チョコ</anser>
</contents>
<contents no="2">
<q>Bさんの好きなスポーツは?</q>
<anser>野球</anser>
</contents>
</question>


ヒント又は参考URLがあったら教えて下さい。
宜しく御願いします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/1/19 06:27:44
> <anser>野球</anser>
answer ですよね。(anser だと金融システムになってしまいます)

で、XmlReader は高速ですが融通が利きにくいので…こんな方法は如何でしょう。

(案1)
Dim doc As XDocument = XDocument.Load("C:\test.xml")
Dim contents1 = doc.<question>.<contents>.Where(Function(x) x.@no = 1)
Dim q As String = contents1.<q>.Value
Dim answer As String = contents1.<anser>.Value
MsgBox(q & vbNewLine & answer)


(案2)
Dim doc As New XmlDocument()
doc.Load("C:\test.xml")
Dim contents1 As XmlNode = doc.SelectSingleNode("/question/contents[@no='1']")
Dim q As String = contents1.SelectSingleNode("q").InnerText
Dim answer As String = contents1.SelectSingleNode("anser").InnerText
投稿者 あにす  (社会人) 投稿日時 2010/1/19 13:47:04
ちょっとした処理では魔界の仮面弁士さんが挙げた方法がとても使いやすいのですが、ある程度の規模のプログラムになる場合はこんな方法も有効です。XMLの構造をプログラム中でクラスとして扱えます。

Imports System.IO
Imports System.Text.Encoding
Imports System.Xml.Serialization

Public Sub SettingFile()
    Try
        Dim contentsList As Question

        Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(Question))

        Using sr As New StreamReader(_filepath, GetEncoding("shift-jis"))
            contentsList = serializer.Deserialize(sr)
        End Using

        For Each contents As Contents In contentsList
            Me.TextBox1.AppendText(contents.No & Environment.NewLine)
            Me.TextBox1.AppendText(contents.Q & Environment.NewLine)
            Me.TextBox1.AppendText(contents.Anser & Environment.NewLine)
            Me.TextBox1.AppendText(Environment.NewLine)
        Next
    Catch ex As Exception
        MessageBox.Show(ex.Message.ToString())
    End Try
End Sub

<XmlType("question")> _
Public Class Question
    Inherits List(Of Contents)
End Class

<XmlType("contents")> _
Public Class Contents
    Dim no_ As Integer
    <XmlAttribute("no")> _
    Public Property No() As Integer
        Get
            Return Me.no_
        End Get
        Set(ByVal value As Integer)
            Me.no_ = value
        End Set
    End Property

    Dim q_ As String
    <XmlElement("q")> _
    Public Property Q() As String
        Get
            Return Me.q_
        End Get
        Set(ByVal value As String)
            Me.q_ = value
        End Set
    End Property

    Dim anser_ As String
    <XmlElement("anser")> _
    Public Property Anser() As String
        Get
            Return Me.anser_
        End Get
        Set(ByVal value As String)
            Me.anser_ = value
        End Set
    End Property
End Class
投稿者 tecc  (社会人) 投稿日時 2010/1/19 17:31:24
お二人方ともありがとうございます。

魔界の仮面弁士さんの案2を使わせて頂きます。

あにすさん 4:47:04 早起きですね・・。
これはシリアライズ?というやつですか、ちょっとこれを使って勉強してみます。

ありがとうございました。 


投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/1/19 19:30:09
(案3)DataSetを使う方法もあります。
Dim ds As New DataSet()
ds.ReadXml("C:\test.xml")
'DataGridView1.DataSource = ds.Tables("contents") 
Dim row As DataRow = ds.Tables("contents").Select("no='1'").First()
If row IsNot Nothing Then
    Dim q As String = CStr(row("q"))
    Dim a As String = CStr(row("anser"))
    MsgBox(q & vbNewLine & a)
End If