C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

XMLを読込後、リストにセットする方法

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■88344 / inTopicNo.1)  XMLを読込後、リストにセットする方法
  
□投稿者/ 河童 (24回)-(2018/08/22(Wed) 12:45:21)

分類:[C#] 

こんにちは、いつも大変お世話になっております。

XMLファイルを読込した後、
リスト型に各要素を1つのレコードとして
セットするにはどのようにすれば、良いでしょうか?
アドバイス、よろしくお願いします。

現状、
リストのカラムが追加されている状態です。
user_id、user_name、jusyoを1つのレコードとして
リストにセットしたいです。


xmlの中身
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <m_user>
    <user_id>20180723173140731</user_id>
    <user_name>testA</user_name>
    <jusyo />
  </m_user>
  <m_user>
    <user_id>20180723173140732</user_id>
    <user_name>testB</user_name>
    <jusyo />
  </m_user>
  <m_user>
    <user_id>20180723173140733</user_id>
    <user_name>testC</user_name>
    <jusyo />
  </m_user>
</NewDataSet>


       private void btnImp_Click(object sender, EventArgs e)
        {
            XmlDocument document = new XmlDocument();

            string xmlFile;
            xmlFile = @".\xml\m_user.xml";

            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();

            // XMLファイルを読み込む
            xmlDoc.Load(xmlFile);

            //ルート要素を取得する
            System.Xml.XmlElement rootElement = xmlDoc.DocumentElement;

            //タグのNodeListを取得する
            System.Xml.XmlNodeList nodelist = rootElement.GetElementsByTagName("user_id");
            System.Xml.XmlNodeList nodelist2 = rootElement.GetElementsByTagName("user_name");
            System.Xml.XmlNodeList nodelist3 = rootElement.GetElementsByTagName("jusyo");

            List<string> list = new List<string>();

            //指定したタグが存在するか?
            if (nodelist.Count > 0)
            {
                for (int i = 0; i < nodelist.Count; ++i)
                {

                    list.Add(nodelist.Item(i).InnerText);
                    list.Add(nodelist2.Item(i).InnerText);
                    list.Add(nodelist3.Item(i).InnerText);
                    

                }

            }

        } 

引用返信 編集キー/
■88346 / inTopicNo.2)  Re[1]: XMLを読込後、リストにセットする方法
□投稿者/ WebSurfer (1583回)-(2018/08/22(Wed) 12:55:00)
No88344 (河童 さん) に返信

> XMLファイルを読込した後、
> リスト型に各要素を1つのレコードとして
> セットするにはどのようにすれば、良いでしょうか?

現状の問題は何なのでしょうか? コードをアップしてますが、それでどのようなことを期待したが、
結果はどうなって、どこが期待と異なるのですか?
引用返信 編集キー/
■88349 / inTopicNo.3)  Re[1]: XMLを読込後、リストにセットする方法
□投稿者/ ????? (3回)-(2018/08/22(Wed) 13:24:18)
No88344 (河童 さん) に返信

えっと、こんな感じでよいのかな?

            //List<string> list = new List<string>();

            ////指定したタグが存在するか?
            //if (nodelist.Count > 0)
            //{
            //    for (int i = 0; i < nodelist.Count; ++i)
            //    {

            //        list.Add(nodelist.Item(i).InnerText);
            //        list.Add(nodelist2.Item(i).InnerText);
            //        list.Add(nodelist3.Item(i).InnerText);


            //    }

            //}

            List<Record> list = new List<Record>();

            //指定したタグが存在するか?
            if (nodelist.Count > 0)
            {
                for (int i = 0; i < nodelist.Count; ++i)
                {
                    list.Add(new Record(nodelist.Item(i).InnerText, nodelist2.Item(i).InnerText, nodelist3.Item(i).InnerText));
                }
            }

            foreach (var r in list)
            {
                Console.WriteLine(r);
            }
        }

        class Record
        {
            public Record(string user_id, string user_name, string jusyo)
            {
                this.user_id = user_id;
                this.user_name = user_name;
                this.jusyo = jusyo;
            }

            public override string ToString()
            {
                return $"{this.user_id},{this.user_name},{this.jusyo}";
            }

            public string user_id { get; }
            public string user_name { get; }
            public string jusyo { get; }
        }

引用返信 編集キー/
■88351 / inTopicNo.4)  Re[1]: XMLを読込後、リストにセットする方法
□投稿者/ 魔界の仮面弁士 (1791回)-(2018/08/22(Wed) 13:52:55)
No88344 (河童 さん) に返信
> user_id、user_name、jusyoを1つのレコードとして
> リストにセットしたいです。

であれば、Record クラスを準備しておくとか。
匿名型やタプルでも良いですけど。

public class Record
{
 public string user_id { get; }
 public string user_name { get; }
 public string jusyo { get; }
 public Record(string user_id, string user_name, string jusyo)
 {
  this.user_id = user_id;
  this.user_name = user_name;
  this.jusyo = jusyo;
 }
 public override string ToString() => $"{user_id},{user_name},{jusyo}";
}


> XMLファイルを読込した後、
> リスト型に各要素を1つのレコードとして
> セットするにはどのようにすれば、良いでしょうか?

案1) LINQ to XML で直接読み取る
List<Record> list1 = (from n in XDocument.Load(@".\xml\m_user.xml").Root.Elements()
 select new Record(n.Element("user_id").Value, n.Element("user_name").Value, n.Element("jusyo").Value)
).ToList();


案2) DataSet に読み込んでから、LINQ to DataSet で加工する

DataSet ds = new DataSet("NewDataSet");
ds.ReadXml(@".\xml\m_user.xml");
List<Record> list2 = ds.Tables["m_user"].AsEnumerable().Select(
 r => new Record(r.Field<string>("user_id"), r.Field<string>("user_name"), r.Field<string>("jusyo"))
).ToList();
引用返信 編集キー/
■88356 / inTopicNo.5)  Re[1]: XMLを読込後、リストにセットする方法
□投稿者/ WebSurfer (1584回)-(2018/08/22(Wed) 14:37:47)
No88344 (河童 さん) に返信

皆さん、私の問い合わせの返事が来る前に案を書いてしまっているので、私も案を書いておきます。
魔界の仮面弁士さんの「案 1」とほとんど同じですが。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ConsoleAppXDocument
{
    class Program
    {
        static void Main(string[] args)
        {
            string filepath = @"C:\Users\...\XMLFile1.xml";
            XDocument doc = XDocument.Load(filepath);

            IEnumerable<M_user> users = from el in doc.Root.Elements()
                                        select new M_user
                                        {
                                            User_id = el.Element("user_id").Value,
                                            User_name = el.Element("user_name").Value,
                                            Jusyo = el.Element("jusyo").Value
                                        };            

            // List<T> 型にしたい場合は以下のように ToList() メソッドを適用
            // List<M_user> list = users.ToList();

            foreach (M_user user in users)
            {
                Console.WriteLine("id: {0}, name: {1}, jusyo: {2}",
                    user.User_id, user.User_name, user.Jusyo);
            }

            // 結果は:
            // id: 20180723173140731, name: testA, jusyo:
            // id: 20180723173140732, name: testB, jusyo:
            // id: 20180723173140733, name: testC, jusyo:
        }
    }

    public class M_user
    {
        public string User_id { get; set; }
        public string User_name { get; set; }
        public string Jusyo { get; set; }
    }
}

引用返信 編集キー/
■88357 / inTopicNo.6)  Re[2]: XMLを読込後、リストにセットする方法
□投稿者/ PANG2 (230回)-(2018/08/22(Wed) 14:47:47)
2018/08/22(Wed) 14:52:28 編集(投稿者)

単純に、m_user[] 型でシリアライズ/デシリアライズすればよいのでは?
引用返信 編集キー/
■88359 / inTopicNo.7)  Re[3]: XMLを読込後、リストにセットする方法
□投稿者/ にゃるら (37回)-(2018/08/22(Wed) 15:48:44)
2018/08/22(Wed) 16:51:22 編集(投稿者)
No88357 (PANG2 さん) に返信
> 2018/08/22(Wed) 14:52:28 編集(投稿者)
> 
> 単純に、m_user[] 型でシリアライズ/デシリアライズすればよいのでは?


以下のようなXmlシリアライズってこと?


using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace test1
{
    public class Loader
    {
        static void Main(string[] args)
        {
            var xmlFile = @".\xml\m_user.xml";
            var ret = Loader.Load(xmlFile);
            if (ret != null)
            {
                foreach (var r in ret)
                {
                    Console.WriteLine(r);
                }
            }
        }

        public static IEnumerable<User> Load(string path)
        {
            try
            {
                using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    var serialiser = new XmlSerializer(typeof(AddressBook));
                    var addressBook = (AddressBook)serialiser.Deserialize(stream);
                    return addressBook.Users;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }
    }

    [XmlRoot("NewDataSet")]
    public class AddressBook
    {
        [XmlElement("m_user")]
        public User[] Users { get;  set; }
    }
    
    public class User
    {
        [XmlElement("user_id")]
        public string user_id { get; set; }

        [XmlElement("user_name")]
        public string user_name { get; set; }

        [XmlElement("jusyo")]
        public string jusyo { get; set; }

        public override string ToString()
        {
            return $"ID:{user_id},Name:{user_name},Address:{jusyo}";
        }
    }
}


※ 別スレッドで既に取り組まれていたことだったのですね。
※ このスレッドしか見てなかったので冗長なことしてしまいました。。。。。

引用返信 編集キー/
■88362 / inTopicNo.8)  Re[1]: XMLを読込後、リストにセットする方法
□投稿者/ 魔界の仮面弁士 (1793回)-(2018/08/22(Wed) 17:35:07)
2018/08/22(Wed) 17:42:52 編集(投稿者)

No88344 (河童 さん) に返信
> <m_user>

先の No88328 で始まる方のスレッドでは、
m_User と m_user が混在していたようなのでご注意を。

m_User がクラス名で
m_user が DataSet 上のテーブル名ですね。


List<m_User> インスタンスの内容をファイルとして保持したいという話なら、
シリアライザの Serialize / Deserialize で十分かと思います。

ただし XmlSerializer については、 No88339 で示したように、
永続化に失敗するパターンがある点に注意してください。

参考までに、シリアライザの比較記事を紹介しておきます。
http://neue.cc/2010/05/29_261.html


一方、複数のデータベース(今回は MySQL ?)のデータ比較が目的なら、
 データベースA → m_User → XML → m_User → データベースB
という流れではなく、 No88331 / No88335 で WebSurfer さんが書かれているように
m_User ではなく DataSet でやり取りした方が手っ取り早い気がします。
(型付DataSet でも、素の System.Data.DataSet でもどちらでも良い)

DataSet の場合の手順については No88347 を参照。XmlWriteMode.DiffGram 指定で
永続化すれば、INSERT/UPDATE/DELETE 操作も自動的に行わせることもできます。
(DataSet の更新結果を伝えるだけで、データベース間で同期をとるためのものではないですが)


もちろん、DataSet を使わず、m_User で処理するのも選択肢の一つです。
(DataSet は多機能な分、処理としては重量級になるので)

ただいずれの方法を取るにせよ、今回のケースでは
XML データに直接アクセスする必要は無いので、
> // XMLファイルを読み込む
> xmlDoc.Load(xmlFile);
のように、XmlDocument などを用いる必要は無いでしょう。

今回の XML 化は手段であって目的ではないので、ファイルへの保存と読み込みは
シリアライザに任せるか、DataSet に任せるかすれば十分に思えます。
引用返信 編集キー/
■88365 / inTopicNo.9)  Re[2]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (25回)-(2018/08/23(Thu) 09:29:10)
おはようございます。
皆様、お返事ありがとうございます。

私が説明不足にもかかわらず、
やりたいことの意図をくみ取っていただいて
ありがとうございました。

本当にいろんな方法があるんですね。

今回、頂いた情報量が多いので、
自分で理解できるまで少しお時間をください。

不明点や処理ができたら
また投稿しますので、よろしくお願いします。


引用返信 編集キー/
■88386 / inTopicNo.10)  Re[3]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (26回)-(2018/08/24(Fri) 17:45:25)
こんばんは。

今回は、WebSurferさんの案で作成しました。
XMLファイルからデータを読込んで、
Foreachでリストにセットすることができました。

LINQの構文が難しいのですが、これはクエリ形式かな。
XMLファイルを読込したときにコレクションをフィルタリングする
ことは可能でしょうか?

Foreachの処理の中で不要なデータを読み飛ばすことはできるのですが、
XMLファイルを読込んだ時点でフィルタリングをかけることができれば、
処理的に効率的かなと思っています。

例えば、
XMLファイルのuser_idが「1001」のみ読込したい場合、
条件として設定することはできますか?

よろしくお願いします。

IEnumerable<m_User> users = from el in doc.Root.Elements()
                            // Where el5.user_ID = "1001"
                            select new m_User





        private void btnImp_Click(object sender, EventArgs e)
        {

            string xmlFile;
            xmlFile = @".\xml\m_user.xml";
           
           // XMLファイルの有無
            if (File.Exists(xmlFile))
            {
                // XMLファイルのロード
                XDocument doc = XDocument.Load(xmlFile);
                // foreachでコレクション処理できるように!!
                IEnumerable<m_User> users = from el in doc.Root.Elements()
                                            select new m_User
                                            {
                                                user_id = el.Element("user_id").Value,
                                                user_name = el.Element("user_name").Value
                                            };

                foreach (m_User user in users)
                {
                    m_User muser = new m_User();
                    muser.user_id = user.user_id;
                    muser.user_name = user.user_name;

                    // 利用者名で検索
                    List<m_User> mUserLst = Pb.Get_m_user_xml(out Pb.Cmn.ErrTxt1, 1, muser.user_name);

                    #region 利用者マスタの移植
                    if (mUserLst.Count == 0 )  // 同名の利用者がいない場合は、新規追加
                    {

                        // 利用者マスタを追加

                    }
                    else  // 同名の利用者がいる場合は、更新処理
                    {

                        // 利用者マスタの更新

                    }
                }

            }        
        }

引用返信 編集キー/
■88387 / inTopicNo.11)  Re[4]: XMLを読込後、リストにセットする方法
□投稿者/ 魔界の仮面弁士 (1796回)-(2018/08/24(Fri) 18:28:30)
No88386 (河童 さん) に返信
> XMLファイルのuser_idが「1001」のみ読込したい場合、
> 条件として設定することはできますか?

やり方は色々ありますが:

案1)
IEnumerable<m_User> users
  = from el in doc.Elements("user_id") where el.Value == "1001"
   select new m_User {
    user_id = el.Value,
    user_name = el.Parent.Element("user_name").Value
   };


案2)
m_User user1001
  = doc.Descendants("m_user")
     .Where(n => n.Element("user_id").Value == "1001")
     .Select(n => new m_User
     {
      user_id = n.Element("user_id").Value,
      user_name = n.Element("user_name").Value
     }).FirstOrDefault();
引用返信 編集キー/
■88405 / inTopicNo.12)  Re[5]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (27回)-(2018/08/27(Mon) 18:09:12)
No88387 (魔界の仮面弁士 さん) に返信

こんばんは。

案1の方で試してみました。

エラーなくビルドはできるのですが、
取得したデータはなくて
where条件がうまくいっていない感じです。

追加で質問です。
固定にしていた値を変数にした場合、
変数の結合はそのままつければよいですか?

また、
LINQの部分の確認方法はどの様にすれば、よいでしょうか?
よろしくお願いします。



string wuser_id;
wuser_id = "1001";

IEnumerable<m_User> users
  = from el in doc.Elements("user_id") where el.Value == wuser_id
   select new m_User {
    user_id = el.Value,
    user_name = el.Parent.Element("user_name").Value
   };

引用返信 編集キー/
■88406 / inTopicNo.13)  Re[6]: XMLを読込後、リストにセットする方法
□投稿者/ 魔界の仮面弁士 (1799回)-(2018/08/27(Mon) 18:55:29)
No88405 (河童 さん) に返信
> 案1の方で試してみました。
> エラーなくビルドはできるのですが、
> 取得したデータはなくて
> where条件がうまくいっていない感じです。

失礼しました……!

doc.Elements("user_id") ではなく
doc.Descendants("user_id") です。


// XDocument doc = XDocument.Parse(xmlText);
XDocument doc = XDocument.Load(@".\xml\m_user.xml");

string wuser_id = "20180723173140732";

IEnumerable<m_User> users = from el in doc.Descendants("user_id")
                            where el.Value == wuser_id
                            select new m_User
                            {
                                user_id = el.Value,
                                user_name = el.Parent.Element("user_name").Value
                            };


> LINQの部分の確認方法はどの様にすれば、よいでしょうか?

LINQ の何を確認したいのでしょうか?

引用返信 編集キー/
■88489 / inTopicNo.14)  Re[7]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (28回)-(2018/09/03(Mon) 20:06:22)
No88406 (魔界の仮面弁士 さん) に返信

こんばんは。

doc.Descendants("user_id")
に変更したのですが、Where句がうまくいきません。
データが何も抽出されません。

> LINQ の何を確認したいのでしょうか?
LINQの部分が正しく動いているのかを確認したいです。
例えば、
SQL文だとコマンドプロンプトでSQL文を実行すると
結果がわかります。
LINQの場合は、コード上で確認するしかないのでしょうか?

引用返信 編集キー/
■88490 / inTopicNo.15)  Re[8]: XMLを読込後、リストにセットする方法
□投稿者/ 魔界の仮面弁士 (1806回)-(2018/09/03(Mon) 21:50:53)
No88489 (河童 さん) に返信
> doc.Descendants("user_id")
> に変更したのですが、Where句がうまくいきません。
> データが何も抽出されません。

当方環境では、
No88344 の "m_user.xml" に対して、
No88406 のコードそのままで抽出されたのですけれどね。
コピー & ペーストしてそのままです。
m_User クラスの定義も、 No88330 の内容と変えていませんし。

こちらで再現できないので理由は分からないのですが、
誤って別のファイルを読み込ませているとか、
もしくは質問( No88344 ) にある XML の内容が、
実際の物と違っていたりはしないでしょうか。(大文字小文字とか)


> SQL文だとコマンドプロンプトでSQL文を実行すると
> 結果がわかります。
コマンドプロンプト…というと、
MySQL にとっての mysql コマンド
SQL Server にとっての osql や sqlcmd コマンド
Oracle にとっての sqlplus コマンド
PostgreSQL にとっての psql コマンドとかですかね。


> LINQの場合は、コード上で確認するしかないのでしょうか?
Visual Studio 2010 をお使いなのでしたっけ。
現行バージョンに乗り換えた方が良いですよ。

古い開発環境だと、イミディエイト ウィンドウで LINQ が使えませんが
現行バージョンならイミディエイト上でも扱えます。
https://qiita.com/gigadein/items/228305a1cc65651c3c2e

また、一時停止中に変数上にマウスポインタを重ねたり、
ウォッチ/クイック ウォッチ、自動変数、ローカル 等のウィンドウで
確認できるリスト内では、『動的ビュー(Results View)』ノードを
クリックすることで、LINQ の抽出結果を確認できます。
引用返信 編集キー/
■88496 / inTopicNo.16)  Re[9]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (30回)-(2018/09/04(Tue) 07:33:56)
No88490 (魔界の仮面弁士 さん) に返信

ありがとうございます。

何か小さな原因でつまずいていると思います。
もう少し自分で調べてみます。

現行バージョンは、
使いやすそうですね。
引用返信 編集キー/
■88497 / inTopicNo.17)  Re[10]: XMLを読込後、リストにセットする方法
□投稿者/ 河童 (31回)-(2018/09/04(Tue) 07:34:03)
No88496 (河童 さん) に返信
> ■No88490 (魔界の仮面弁士 さん) に返信
>
> ありがとうございます。
>
> 何か小さな原因でつまずいていると思います。
> もう少し自分で調べてみます。
>
> 現行バージョンは、
> 使いやすそうですね。
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ