トップ回答者
xmlから結果を抜き出したい

質問
-
いつもお世話になります。
VisualC#2010、WindowsXPでの動作について質問があります。
下記のxml文書から、fictionの場合の結果のみを抜き出したいと考えています。<?xml version="1.0" encoding="UTF-8" ?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:test:jp:jlp" xsi:schemaLocation="urn:test:jp:jlp http://jlp.testapis.jp/Service/photoResponse.xsd">
<allresult>
<total_count>4</total_count>
<filtered_count>4</filtered_count>
<name_list>
<name><view>明智小五郎</view><kana>あけちこごろう</kana><status>fiction</status></name>
<name><view>明智光秀</view><kana>あけちみつひで</kana><status>real</status></name>
<name><view>遠藤平吉</view><kana>えんどうへいきち</kana><status>fiction</status></name>
<name><view>遠藤周作</view><kana>えんどうしゅうさく</kana><status>real</status></name>
</name_list>
</uniq_result>
</ResultSet>XDocument xdoc = XDocument.Parse(xml);
string answer = "";
var query = from result in xdoc.Root.Elements("allresult").Elements("name_list").Elements("name")
where result.Elements("status").Value == "fiction"
select new{
list = result.Elements("view").Value
};
foreach (var q in query) answer += q.list;とコードを書くと、
where result.Elements("status").Value == "fiction"
list = result.Elements("view").Value
の行で、.Valueはないとエラーになります。
そこで、そこをToString()にしてみたのですが、コンパイルはできるのですが、実行すると、nullになってエラーとなります。
xdoc.Root.Elements("allresult")
のところで、xdocのRootにあるのは、ResultSetなので、from result in xdoc.Root.Elements("ResultSet").Elements("allresult").Elements("name_list").Elements("name")
としてもだめでした。
名前空間かと思って、
XNamespace xnamespace = "urn:test:jp:jlp";
XNamespace xnamespace = "http://www.w3.org/2001/XMLSchema-instance";
のように指定してみてもダメでした。
添削よろしくお願いします。
回答
-
XML名前空間を使っているので、ElementやElementsで子要素を取得するときに、要素名だけでなくXNamespaceも指定する必要があります。
こんな感じになります。
XDocument xdoc = XDocument.Load("sample.xml"); var ns = XNamespace.Get("urn:test:jp:jlp"); var query = from result in xdoc.Root .Element(ns + "allresult") .Element(ns + "name_list") .Elements(ns + "name") where result.Element(ns + "status").Value == "fiction" select new { list = result.Element(ns + "view").Value };
なかむら(http://d.hatena.ne.jp/griefworker)- 回答としてマーク HANA01 2010年10月11日 4:28
-
動作は確認していませんが、こんな感じでしょうか?
Elementsは子要素のコレクションを返すので、Valueプロパティが無いようです。
あと、Xml定義に関してですが、allresultノードが閉じられていません。ご確認ください。
var xdoc = XDocument.Parse(xml);
string answer = "";
var query = from result in xdoc.Root.Elements("allresult")
.Elements("name_list")
.Elements("name")
where result.Element("name").Value == "fiction"
select new {list = result.Value };
foreach (var q in query) answer += q.list;- 回答としてマーク HANA01 2010年10月11日 4:28
すべての返信
-
XML名前空間を使っているので、ElementやElementsで子要素を取得するときに、要素名だけでなくXNamespaceも指定する必要があります。
こんな感じになります。
XDocument xdoc = XDocument.Load("sample.xml"); var ns = XNamespace.Get("urn:test:jp:jlp"); var query = from result in xdoc.Root .Element(ns + "allresult") .Element(ns + "name_list") .Elements(ns + "name") where result.Element(ns + "status").Value == "fiction" select new { list = result.Element(ns + "view").Value };
なかむら(http://d.hatena.ne.jp/griefworker)- 回答としてマーク HANA01 2010年10月11日 4:28
-
動作は確認していませんが、こんな感じでしょうか?
Elementsは子要素のコレクションを返すので、Valueプロパティが無いようです。
あと、Xml定義に関してですが、allresultノードが閉じられていません。ご確認ください。
var xdoc = XDocument.Parse(xml);
string answer = "";
var query = from result in xdoc.Root.Elements("allresult")
.Elements("name_list")
.Elements("name")
where result.Element("name").Value == "fiction"
select new {list = result.Value };
foreach (var q in query) answer += q.list;- 回答としてマーク HANA01 2010年10月11日 4:28
-
アドバイスありがとうございます。
from result in xdoc.Root.Elements("allresult").Elements("name_list").Elements("name")
を、
from result in xdoc.Root.Element("allresult").Element("name_list").Elements("name")
にしました。
Elementは単独で、Elementsは配列ということなのでしょうか。それで、デバッグで実行してみると、
foreach (var q in query) answer += q.list;
のところで、qのbase-valueというところに、明智小五郎という値が入っているのは見えたのですが、このとおり実行していくと、answerには、
System.Xml.Linq.XContainer+<GetElements>d__11
という文字列しか入りません。
q.list;
でなくて、別の書き方をしないとだめっぽいのですが、
q.Valueとかではだめみたいです。
ここはどうしたらよいでしょう? -
みなさんありがとうございます。
その後もいろいろ試していて、xnamespaceが邪魔なので、
xml = xml.Replace("<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:test:jp:jlp" xsi:schemaLocation="urn:test:jp:jlp http://jlp.testapis.jp/Service/photoResponse.xsd">","");
とかやって、namespaceを削除してみたりしていましたが、いまいちわかっていませんでしたが、わかりました!
ElementsとElementは別だったのですね。where result.Elements("status").Value == "fiction"
select new{
list = result.Elements("view").Valuewhere result.Element("status").Value == "fiction"
select new{
list = result.Element("view").Value
としたところ、Valueを取り出せて、うまくいきました。XML定義ですが、適当に上半分抜いたところ、閉じてないように見えましたが、オリジナルのデータは閉じてありました。
ありがとうございました。