こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

XMLからデータを取得

いつもお世話になっております。

XMLファイルに含まれたデータの中から、特定のデータを検索するプログラムを作りたいと思っております。

<AAA Name="テスト">
   <BBB x="2" y="2"></BBB>
   <CCC Num="0001"></CCC>
   <CCC Num="0002"></CCC>
</AAA>
XMLデータの形式は↑みたいな感じで、これが100以上あり、CCCタグは0~5個までです。

フォームにテキストボックスを配置し、そこに検索したい語句を入れ、
AAAタグのNameの中身と合致したら、BBB、CCCの属性をすべて取得して表示するということをしたいのですが、
どうにも上手くいきません。

VB2008を使用しております。
方法をご存知の方、ご教授ください……orz

投稿日時 - 2009-04-29 17:00:27

QNo.4918417

すぐに回答ほしいです

質問者が選んだベストアンサー

a_navi.Select("//AAA[@Name='test']")
で AAAタグの検索条件を増やさないのであれば

xml_data = a_navi.Select("//AAA[@Name='test']")
while xml_data.MoveNext
  Dim xmldoc As New Xml.XmlDocument
  ' XMLDocumentに 選択されたCurrentのOuterXmlを与えれば
  ' 自前で XML形式の体裁を整える必要がありません
  xmldoc.loadXML( xml_data.Current.OuterXml)
  ' StringReaderにも OuterXmlで与えます
  a_xml = new Xml.XmlTextReader(New IO.StringReader(xml_data.DocumentElement.OuterXml))
  while a_xml.Read
    If a_xml.NodeType = XmlNodeType.Element Then
      Select Case a_xml.LocalName
        ' AAAタグ用の分岐を定義
        Case "AAA"
          Console.WriteLine("aaa:" & a_xml.GetAttribute("age") & "," & a_xml.GetAttribute("id"))
        Case "BBB"
          Console.WriteLine("bbb:" & a_xml.GetAttribute(0) & "," & a_xml.GetAttribute(1))
        Case "CCC"
          Console.WriteLine("ccc:" & a_xml.GetAttribute(0))
      End Select
    End If
  end while
end while

といった具合でよさそうですよ

投稿日時 - 2009-05-01 01:16:36

お礼

何度もありがとうございます。今後属性が増えても大丈夫そうです。
これを機にもう少しXMLの扱いを勉強していきたいと思います。

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

投稿日時 - 2009-05-01 18:44:23

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

> もしAAAタグのName以外に属性があるとしたら、どのようにすれば
> 取得できるのでしょうか?
具体例を挙げて質問してみましょう

<AAA Name="test" att1="sub1">
  <bbb x="1" y="2"/>
</AAA>
<AAA Name="test">
  <bbb x="3" y="4"/>
</AAA>
<AAA Name="test" att1="sub2">
  <bbb x="5" y="6"/>
</AAA>
<AAA Name="test" att2="ext1">
  <bbb x="5" y="6"/>
</AAA>
といったデータの場合

a_navi.Select("//AAA[@Name='test']")
とすれば 4要素すべて取得します

a_navi.select("//AAA[@Name='test'][@att1]")
とすれば Name="test" かつ att1がある要素が選択されます

a_navi.select("//AAA[@Name='test'][@att1='sub1']")
とすれば Name="test" かつ att1="sub1"の要素が選択されます

投稿日時 - 2009-04-30 01:47:58

お礼

>具体例を挙げて質問してみましょう
またもや失礼しました、二回目なのに……
たくさんの例まであげていただいてありがとうございます。
検索条件を絞ることもできるんですね。

<AAA Name="test" Age="20" Id="123456">
   <BBB x="2" y="2"></BBB>
   <CCC Num="0001"></CCC>
   <CCC Num="0002"></CCC>
</AAA>
となっていた時、Nameで検索しヒットしたら、BBB、CCCタグの属性と一緒にAAAタグのAge、Idも取得するというものでした。

もし差し支えございませんでしたらまたご教授ください……
何度もすみません……

投稿日時 - 2009-04-30 17:52:42

ANo.2

xml_dataでMoveNextを行っていないのが原因のように思います

  dim xml_data as System.Xml.XPath.XPathNodeIterator = a_navi.Evaluate("//AAA[@Name='(検索条件)']")

  while xml_data.MoveNext
  dim sbl as new Text.StringBuilder
  ' XMLの体裁を整える
  sbl.AppendLine("<dummyroot>")
  sbl.Append( xml.Current.InnerXml )
  sbl.AppendLine("</dummyroot>")
  dim a_xml as a_xml As New System.Xml.XmlTextReader(New System.IO.StringReader(sbl.toString))
  While a_xml.Read
    If a_xml.NodeType = Xml.XmlNodeType.Element Then
      Select Case a_xml.LocalName
        Case Is = "BBB"
          Console.WriteLine("xの値:" & a_xml.GetAttribute(0) & " yの値:" & a_xml.GetAttribute(1))
        Case Is = "CCC"
          Console.WriteLine("Numの値:" & a_xml.GetAttribute(0))
      End Select
    End If
  End While

といった具合で

xml_data.MoveNextを実行することによりxml_data.Current.InnerXmlが
<AAA Name="テスト">
   <BBB x="2" y="2"></BBB>
   <CCC Num="0001"></CCC>
   <CCC Num="0002"></CCC>
</AAA>
の抽出部分だけになりますので
これを StringBuilderにて
<dummyroot>
  <AAA Name="テスト">
   <BBB x="2" y="2"></BBB>
   <CCC Num="0001"></CCC>
   <CCC Num="0002"></CCC>
  </AAA>
</dummyroot>
といった具合にXMLの体裁を整えて XmlTextReaderに与えています

投稿日時 - 2009-04-29 21:47:26

お礼

ありがとうございます、無事に動きました。
ソースだけでなく、XMLのほうがどうなっているのかも書いていただきありがとうございます。
StringBuilderなんて初めて見た……勉強になります。

ついで……といってはアレですが、
もしAAAタグのName以外に属性があるとしたら、どのようにすれば取得できるのでしょうか?
もしよろしければ、ご教授お願いします。

投稿日時 - 2009-04-29 23:33:19

ANo.1

> どうにも上手くいきません。
と抽象的な表現をするのではなく、現在実行しているコード、そのデータ、実行結果、希望する結果
などを明示して質問しましょう

データ自体を DataSetまたはDataTableへ読み込んでいるのか
Sysytem.Xmlクラスで実行しているのか
によってもコーディングは変わってきますよ

投稿日時 - 2009-04-29 18:53:09

補足

失礼しました、上の質問の内容の補足として付け加えさせていただきます。
XMLの読み込みは、XPathを使って以下のようにやってます。

Dim A As New System.Xml.XPath.XPathDocument("test.xml")
Dim a_navi As System.Xml.XPath.XPathNavigator = A.CreateNavigator
Dim xml_data As System.Xml.XPath.XPathNodeIterator = a_navi.Evaluate("//AAA[@Name='(検索条件)']")
Dim a_xml As System.Xml.XmlTextReader = New System.Xml.XmlTextReader(New System.IO.StringReader(xml_data.Current.InnerXml))

While a_xml.Read
  If a_xml.NodeType = Xml.XmlNodeType.Element Then
    Select Case a_xml.LocalName
      Case Is = "BBB"
        Console.WriteLine("xの値:" & a_xml.GetAttribute(0) & " yの値:" & a_xml.GetAttribute(1))
      Case Is = "CCC"
        Console.WriteLine("Numの値:" & a_xml.GetAttribute(0))
    End Select
  End If
End While

このコードだと、AAAタグのNameと合致した部分の子ノードだけでなく、
XMLファイルの上から下まで全部を出力してしまいました。

投稿日時 - 2009-04-29 20:20:39

あなたにオススメの質問