ここから本文です

XDocumentによるXML文書の読込について教えてください。 汎用機のシステム開発を...

yut********さん

2017/6/3017:11:39

XDocumentによるXML文書の読込について教えてください。
汎用機のシステム開発をしてきましたが、.NET、C#などはほぼ初心者です。
宜しくお願いします。

以下の処理で、strの内容によってエラーが発生してしまいますがなぜでしょうか。
(エラーは「System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。」です。)

処理:
var xdoc = XDocument.Parse(str);
var xelements = xdoc.Root.Elements();
foreach (var xbook in xelements)
{
XElement xid = xbook.Element("ID");
XElement xtitle = xbook.Element("Title");
XElement xprice = xbook.Element("Price");
XElement xpages = xbook.Element("Pages");
string strid = xid.Value; <--------------------ここでエラー発生
string strtitle = xtitle.Value;
string strprice = xprice.Value;
string strpages = xpages.Value;
string[] xrow = { strid, strtitle, strprice, strpages };
listView1.Items.Add(new ListViewItem(xrow));
}

エラーが発生するXML:
<ArrayOfBook xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/web460.Models"> <-----この行だけ違います。
<Book><ID>1</ID><Pages>250</Pages><Price>1000</Price><Title>タイトル1</Title></Book>
<Book><ID>2</ID><Pages>350</Pages><Price>1200</Price><Title>タイトル2</Title></Book>
<Book><ID>3</ID><Pages>256</Pages><Price>1550</Price><Title>タイトル3</Title></Book>
</ArrayOfBook>

エラーが発生しないXML:
<ArrayOfBook>
<Book><ID>1</ID><Pages>250</Pages><Price>1000</Price><Title>タイトル1</Title></Book>
<Book><ID>2</ID><Pages>350</Pages><Price>1200</Price><Title>タイトル2</Title></Book>
<Book><ID>3</ID><Pages>256</Pages><Price>1550</Price><Title>タイトル3</Title></Book>
</ArrayOfBook>

閲覧数:
80
回答数:
1
お礼:
100枚

違反報告

ベストアンサーに選ばれた回答

tor********さん

2017/7/121:45:06

エラーになると示されているXML内容では、ルート要素であるArrayOfBook要素に対してxmlnsという属性がついていますよね。
これは、(C#とか.NETではなく)XMLの仕様として定められている名前空間というものです。
名前空間はごく簡単に言うと、グループみたいなものです。
そのXMLの例だと、ArrayOfBook要素はhttp://schemas.datacontract.org/2004/07/web460.Models名前空間に属している、という書き方になっています。

質問内でエラーになっているのは、要素取得時の情報が不完全で、要素が取得できていないためです。
「ID」という名前の要素は存在しなくて、存在するのは「http***名前空間のID」という要素だからです。
正しく要素を取得するためには、Element()に名前空間付きで要素名を指定する必要があります。
以下にいくつか例を示します。
# URL形式の文字列をたくさん含むと投稿エラーになるため、名前空間部分は一部省略をしています。
# 実際には名前空間を明示的に指定する場合は正しい内容を指定してください。

// ここではとりあえず、エラーになる例の内容のXMLを読み込んで
// 最初のBook要素を使う場合、という例示とする。
var xmlDoc = XDocument.Load("XMLFile1.xml");
var firstBookElem = xmlDoc.Root.Elements().First();

{// 方法1:該当の名前空間オブジェクト(XNamespace)を作成して名前と結合する
// 特定の名前空間名を指定したい、という場合はこれが素直な方法
var xmlNs = XNamespace.Get("http://schemas.datacontract.org/2004/07/web460.Models");
var idElem = firstBookElem.Element(xmlNs + "ID");
var idString = idElem.Value;
System.Diagnostics.Debug.WriteLine("Method1:" + idString);
}

{// 方法2:特定の要素についている名前空間があればそれを使う
// どこかの要素と同じ、など、特定の文字列とは限らない場合などに有効だと思われる。
// ここではルート要素の名前空間を取得してそれを利用
var xmlNs = xmlDoc.Root.Name.Namespace;
var idElem = firstBookElem.Element(xmlNs + "ID");
var idString = idElem.Value;
System.Diagnostics.Debug.WriteLine("Method2:" + idString);
}

{// おまけ:名前空間オブジェクトにしなくても、XNameの作成で名前空間を指定することもできる。
// Element()で要素を取得する際、"ID"などの文字列を指定しても、実際は暗黙にXNameオブジェクトが作られて渡されている。

// 名前空間を指定してXNameオブジェクトを明示的に取得する例。
var idElem1 = firstBookElem.Element(XName.Get("ID", "http:*****"));
// 名前空間を指定する書式で文字列から暗黙にXNameを作らせる例
var idElem2 = firstBookElem.Element("{http:*****}ID");
System.Diagnostics.Debug.WriteLine("Omake1:" + idElem1.Value);
System.Diagnostics.Debug.WriteLine("Omake1:" + idElem2.Value);
}

  • 質問者

    yut********さん

    2017/7/210:53:53

    toras9000さん、ありがとうございます。

    方法1で解決しました。
    方法2・おまけにつきましても、この後試してみようと思います。
    大変助かりました。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

あわせて知りたい

この質問につけられたタグ

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる