DOBON.NET DOBON.NETプログラミング掲示板過去ログ

フォーム内のコントロールをxml型でSqlserverに保存

環境/言語:[環境Windows7 使用言語VB2013+Sqlserver2008]
分類:[.NET]

いつも参考にさせていただいております。全くの初心者で申し訳ありませんが教えてください。

実行したい内容
SqlserverのXml型に保存されているXml文を取得、操作したいのですが方法がわかりません。テキストでは取得できましたがその先のxml型への変換?がわからず色々調べたのですがXmlファイルをデシリアライズするのは理解しましたがテキストで取得したXMLデータの操作の仕方がわかりません。よろしくお願いします。
何が分からないのかが読み取りづらいというか読み取れません。

XmlSerializerを使ってシリアライズおよびデシリアライズしたい。
DBからXMLをStringとして取ってくることはできた。
このStringを使ってXmlSerializer.Deserializeするにはどうすればいいか。
ということでしょうか?
であれば、StringReaderを使うことでDeserializeに渡せるようになります。
■No32544に返信(Hongliangさんの記事)
回答ありがとうございます。質問の内容が漠然として申し訳ありません。

> XmlSerializerを使ってシリアライズおよびデシリアライズしたい。
はい デシリアライズしたいです。
> DBからXMLをStringとして取ってくることはできた。
> このStringを使ってXmlSerializer.Deserializeするにはどうすればいいか。
> ということでしょうか?
> であれば、StringReaderを使うことでDeserializeに渡せるようになります。
はいstringreaderの使用法がわかりません。どのようにDeserializeに渡すのでしょうか?
■No32545に返信(yamaさんの記事)
> はいstringreaderの使用法がわかりません。どのようにDeserializeに渡すのでしょうか?

教えてもらったキーワードで検索してみましょう。
今回のケースでは「StringReader XmlSerializer Deserialize」です。
これで Google 検索にかけると、3 〜 4 番目ぐらいで良さそうな情報を拾えます。

確かにキーワード検索で求める答えと違うものが出る可能性はあります。
少し違うなと思ったら、上位 10 位以内程度であれば次々とみていきましょう。
それでもよい情報に巡り会えない場合はキーワードが足りていないか、間違っているケースです。


さて、今回の場合、検索によって得られるとは思いますが、紹介しておきますと、StringReader のコンストラクタ引数に string を渡して StringReader のインスタンスを作り、そのインスタンスを XmlSerializer.Deserialize に渡せばよいのです。
それぞれコンストラクタ、Deserialize メソッドのオーバーロードについて調べてみてください。

http://msdn.microsoft.com/ja-jp/library/system.io.stringreader.stringreader(v=vs.110).aspx
http://msdn.microsoft.com/ja-jp/library/system.xml.serialization.xmlserializer.deserialize(v=vs.110).aspx

※Deserialize(TextReader) のドキュメントを読むと、StringReader クラスが TextReader の継承クラスであることがわかります。
2014/08/13(Wed) 10:19:59 編集(投稿者)

返信ありがとうございます。教えていただきました方法を試しております。

Public Class xml
Public Sub デシリアライズ(ByRef xmlドキュメント)
Dim aLine, aParagraph As String
Dim strReader As New StringReader(xmlドキュメント)
While True
aLine = strReader.ReadLine()
If aLine Is Nothing Then
aParagraph = aParagraph & vbCrLf
Exit While
Else
aParagraph = aParagraph & aLine & " "
End If
End While
Console.WriteLine("Modified text:" & vbCrLf & vbCrLf & _
aParagraph)

'XMLドキュメントを逆シリアル化する
Dim serializer As New System.Xml.Serialization.XmlSerializer( _
GetType(xml))
Dim obj As xml = _
DirectCast(serializer.Deserialize(strReader), xml)
end sub
end class
StringReaderの動作は確認できましたが最終行でエラーが表示されます。申し訳ありませんがご指導ください。
2014/08/13(Wed) 17:39:08 編集(投稿者)

■No32547に返信(yamaさんの記事)
> StringReaderの動作は確認できましたが最終行でエラーが表示されます。申し訳ありませんがご指導ください。

エラーが出るというのならそのエラー情報を一緒に書いてください。
今の状況では原因を想像で考えるしかなくなり、正確な助言が難しくなるためです。

ところで、なぜ StringReader から一度全部読んでいるんでしょうか?
(文字列を得るだけならあえて Read せず、元の「xmlドキュメント」という名前の変数をそのまま Console.WriteLine に渡すのが速いため)

StringReader は「現在位置を覚えておき、次に Read されたら前回の続きから読み込めるようにするクラス」です。
最後まで読み込んでしまってから、そのインスタンスを使い回そうとすると「もう読み込める文字列はない」という状態になります。
2014/08/13(Wed) 20:41:01 編集(投稿者)

■No32549に返信(yamaさんの記事)
> 2014/08/13(Wed) 20:05:40 編集(投稿者)
>
> 回答ありがとうございます。
>>エラーが出るというのならそのエラー情報を一緒に書いてください。
>>今の状況では原因を想像で考えるしかなくなり、正確な助言が難しくなるためです。

型 'System.InvalidOperationException' のハンドルされていない例外が System.Xml.dll で発生しました

追加情報:XML ドキュメント (1,2) でエラーが発生しました。

と表示されます。

>>ところで、なぜ StringReader から一度全部読んでいるんでしょうか?
>>(文字列を得るだけならあえて Read せず、元の「xmlドキュメント」という名前の変数をそのまま Console.WriteLine に渡すのが速いため)
申し訳ありません。

実装したい機能を整理しました。
@dt内に保存されているxmlドキュメント(ID,利用者名,パスワード等)からIDと利用者だけ抜きだし保存。
Public Sub 利用者(ByRef 利用者dt As DataTable, ByRef max_cnt As Integer)

Dim cnt As Integer
dt.Columns.Add("ID", Type.GetType("System.Int32"))
dt.Columns.Add("利用者名", Type.GetType("System.String"))
dt.Columns.Add("Name", Type.GetType("System.String"))
dt.Columns.Add("パスワード", Type.GetType("System.String"))
max_cnt = max_cnt - 1
For cnt = 0 To max_cnt
dt.Rows.Add()

xmlドキュメント = 利用者dt(cnt)(1)・・・ここにxmlドキュメントが                         保存されております。

      Dim des As New コントロール
des.デシリアライズ(xmlドキュメント)

Next
End Sub
Public Sub デシリアライズ(ByRef xmlドキュメント)
Dim aLine, aParagraph As String
Dim strReader As New StringReader(xmlドキュメント)

'XMLファイルから読み込み、逆シリアル化する
Dim serializer As New System.Xml.Serialization.XmlSerializer( _
GetType(コントロール))

Dim obj As コントロール = _
DirectCast(serializer.Deserialize(), コントロール)
End Sub


xmlドキュメント
<?xml version="1.0" encoding="UTF-8"?>
-<xmlクラス xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID>1</ID>
<利用者>佐藤</利用者>
<パスワード>1</パスワード>
<DVD>-1</DVD>
</xmlクラス>
2014/08/13(Wed) 21:20:15 編集(投稿者)

■No32549に返信(yamaさんの記事)
> 実装したい機能を整理しました。
> @dt内に保存されているxmlドキュメント(ID,利用者名,パスワード等)からIDと利用者だけ抜きだし保存。

2番がないようですが…。
提示されているコードでは以下の2カ所が気にかかります。

>       Dim des As New コントロール
> des.デシリアライズ(xmlドキュメント)

ここでまず一度 New で新しいインスタンスを作っていますね。

> Dim obj As コントロール = _
> DirectCast(serializer.Deserialize(), コントロール)

ここで Deserialize によってもう一つインスタンスができようとしています。
最初の dest とはまったく関係のない obj ができあがっているので、それでかまわないのか?という疑問を持ちます。
XmlSerializer の Deserialize はあくまで「新しいインスタンスとしてデシリアライズする」なので、このままではプログラムとしてつながりません。
インスタンスの生成をデシリアライズの1カ所にまとめるか、デシリアライズするものをコントロールではなく、別のものにするかでしょうか。


<ここから撤回します>
個人的に思うところとしては、コントロールをデシリアライズするのではなく、自分に必要なデータを入れたクラスをデシリアライズすることを目指した方がよいとは思います。
<ここまで撤回します>

<ここから追記>
「コントロール」という名前の自作クラスのようなので、前述の部分は撤回します。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=73046 を受けて。
<ここまで追記>


ところで、元の XML は XmlSerializer の出力でしょうか?
今回作るコードとは別にすでに存在している XML を読み込むことを目的としているのであれば、XmlSerializer でも実現できるパターンもあれば、実現できないパターンもあり得ます。

> xmlドキュメント
> <?xml version="1.0" encoding="UTF-8"?>
> -<xmlクラス xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> <ID>1</ID>
> <利用者>佐藤</利用者>
> <パスワード>1</パスワード>
> <DVD>-1</DVD>
> </xmlクラス>

これは原文のままでしょうか?
xmlクラスの直前に余計なハイフンが入っていますので不思議な印象を受けます。
- のあるまま Deserialize にかけると「追加情報:XML ドキュメント (2,1) でエラーが発生しました。」となりました。
ご提示のエラーと、行番号と列番号が違うので、同じ問題かの確証はありませんが…。
色々とありがとうございました。最終的にご指摘の通りテキストで取得した内容から抜き出す方法にいたしました。
今後ともよろしくお願いいたします。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板