質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.90%

XMLファイルのデシリアライズ

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 3,930

score 81

「階層化された繰返し要素のXMLをデシリアライズする」
http://zero-config.com/dotnet/xmlserializer002.html

この入門サイト(?)の内容を改造します。
<user>と同じ階層に要素を追加してみます("admin"と名付けました)。

できたXML
<?xml version="1.0" encoding="utf-8"?>
<system-config>
  <system-name>XXXXX</system-name>
  <version>1.1</version>
  <users>
    <user id="0001">
      <email>foo@example.com</email>
      <expired>2015/12/31</expired>
    </user>
    <user id="0002">
      <email>bar@example.com</email>
      <expired>2015/09/30</expired>
    </user>
    <admin id="000a">
      <email>foo@example.com</email>
      <expired>2015/12/31</expired>
    </admin>
    <admin id="000b">
      <email>bar@example.com</email>
      <expired>2015/09/30</expired>
    </admin>
  </users>
</system-config>

こうした場合でのクラス設計がわかりません。
"public class SystemConfig"の書き方がミソだとは思うのですが、色々試しても処理が通りません。

通らない例
/// <summary>
    /// システム設定
    /// </summary>
    [System.Xml.Serialization.XmlRoot("system-config")]
    public class SystemConfig
    {
        /// <summary>
        /// システム名
        /// </summary>
        [System.Xml.Serialization.XmlElement("system-name")]
        public string SystemName {get; set;}
        /// <summary>
        /// バージョン
        /// </summary>
        [System.Xml.Serialization.XmlElement("version")]
        public string Version { get; set; }
        /// <summary>
        /// ユーザ情報
        /// </summary>
        [System.Xml.Serialization.XmlArray("users")]
        [System.Xml.Serialization.XmlArrayItem("user")]
        public List<Sample.Model.User> Users { get; set; }
    ///アドミニ情報
    [System.Xml.Serialization.XmlArray("users")]
        [System.Xml.Serialization.XmlArrayItem("admin")]
        public List<Sample.Model.Admin> Admins{ get; set; }
    }

・
・
・

UserクラスをコピペしたAdminクラスを宣言


丸投げ気味な質問になってしまってますが、よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

usersに入れられるクラスは一種類だけです。他のクラスは入りません。(userとadminの共有はできない)
ですので、以下の様にUserクラスを拡張してみるのはいかがでしょうか?

/// <summary>
    /// ユーザ情報
    /// </summary>
    [Serializable]
    public class User
    {
        /// <summary>
        /// ID
        /// </summary>
        [System.Xml.Serialization.XmlAttribute("id")]
        public string Id { get; set; }
        /// <summary>
        /// メールアドレス
        /// </summary>
        [System.Xml.Serialization.XmlElement("email")]
        public string MailAddress {get; set;}
        /// <summary>
        /// 有効期限
        /// </summary>
        [System.Xml.Serialization.XmlElement("expired")]
        public string Expired { get; set; }

        // 以下を追加

        /// <summary>
        /// 役割
        /// </summary>
        [System.Xml.Serialization.XmlElement("role")]
        public string Role { get; set; }
    }
<?xml version="1.0" encoding="utf-8"?>
<system-config>
  <system-name>XXXXX</system-name>
  <version>1.1</version>
  <users>
    <user id="0001">
      <email>foo@example.com</email>
      <expired>2015/12/31</expired>
      <role>user</role>
    </user>
    <user id="0002">
      <email>bar@example.com</email>
      <expired>2015/09/30</expired>
      <role>user</role>
    </user>
    <userid="000a">
      <email>foo@example.com</email>
      <expired>2015/12/31</expired>
      <role>admin</role>
    </user>
    <userid="000b">
      <email>bar@example.com</email>
      <expired>2015/09/30</expired>
      <role>admin</role>
    </user>
  </users>
</system-config>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/08 18:17 編集

    もうひとつ考えられるのはUsersとは別にAdminsを作ってしまう事です。
    以下サンプル

    c#
    ///アドミニ情報
    [System.Xml.Serialization.XmlArray("admins")] // ←ここをadminsにする
    [System.Xml.Serialization.XmlArrayItem("admin")]
    public List<Sample.Model.Admin> Admins{ get; set; }

    xml
    <?xml version="1.0" encoding="utf-8"?>
    <system-config>
    <system-name>XXXXX</system-name>
    <version>1.1</version>
    <users>
    <user id="0001">
    <email>foo@example.com</email>
    <expired>2015/12/31</expired>
    </user>
    <user id="0002">
    <email>bar@example.com</email>
    <expired>2015/09/30</expired>
    </user>
    </users> ←userはusersの中に入れる
    <admins> ←adminはadminsの中に入れる
    <admin id="000a">
    <email>foo@example.com</email>
    <expired>2015/12/31</expired>
    </admin>
    <admin id="000b">
    <email>bar@example.com</email>
    <expired>2015/09/30</expired>
    </admin>
    </admins>
    </system-config>

    キャンセル

  • 2016/09/09 11:40

    で、できた。素直にXmlElementで作っていけばよかったのですね。ありがとうございます。

    キャンセル

0

C#については、ほとんど、門外漢なのですが、 users 要素に対する宣言が2つあり、余計なように見えます。

/// <summary>
    /// ユーザ情報
    /// </summary>
    [System.Xml.Serialization.XmlArray("users")]
    [System.Xml.Serialization.XmlArrayItem("user")]
    public List<Sample.Model.User> Users { get; set; }
    ///アドミニ情報
    [System.Xml.Serialization.XmlArrayItem("admin")]
    public List<Sample.Model.Admin> Admins{ get; set; }

 

ではだめでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

既にに解決しているようですが、XMLについて他のやり方も書き残します。
※質問時点のXMLの構造は適切ではないので、ishi9様の回答のようにroleを付け加えるのが一番いいです。

  • Classを自動で生成する方法
    img]

  • Classを作成せずに動的にXMLを扱う方法

var str = @"<xml> ... </xml>"
var xml = XDocument.Parse(str);
var version = xml.Element("system-config").Element("version").Value;
foreach (var x in xml.Element("system-config").Element("users").Elements("user"))
{
  Console.WriteLine(x.Element("email").Value);
}

foreach (var x in xml.Element("system-config").Element("users").Elements("admin"))
{
  Console.WriteLine(x.Element("email").Value);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/13 11:06

    わざわざありがとうございます。しかしちんぷんかんぷんなので、「ホニャララでググれ」的なことを教えていただけないでしょうか

    キャンセル

  • 2016/09/15 05:20

    Classを自動で生成する方法 については、
    手動でクラスを書いているのかと思ったので、XMLをコピーした状態で「XMLをクラスとして貼り付ける」を選択すると自動でクラスが生成されるという意味でした。
    何も考えずにXMLクラスを自動で生成してくれるので楽ですし、巨大かつ構造が複雑なXMLの場合にヒューマンエラーを防ぐことができます。

    Classを自動で生成する方法 については、
    System.Xml.Serialization.XmlSerializer を使うのではなく、
    System.Xml.Linq.XDocument を使う方法もあるという紹介でした。
    System.Xml.Linq.XDocument を使うと、classの生成が不要です。

    キャンセル

  • 2016/09/15 17:20

    重ねてわざわざありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.90%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る