すべての子ノードの価値ではなくXelementの値を取得する方法は?
質問
サンプルXML:
<parent>
<child>test1</child>
<child>test2</child>
</parent>
親がXelementであるparent.valueを探した場合、「test1test2」を取得します。私が期待しているのは「」です。 (テキスト/値がないため。
どのようなXelementの財産を探していますか?
解決
でテキストデータを探しているとき <parent>
要素あなたは持っている子ノードを探す必要があります NodeType
に等しいプロパティ XmlNodeType.Text
. 。これらのノードにはタイプがあります XText
. 。次のサンプルはこれを示しています:
var p = XElement
.Parse("<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
var textNodes = from c in p.Nodes()
where c.NodeType == XmlNodeType.Text
select (XText)c;
foreach (var t in textNodes)
{
Console.WriteLine(t.Value);
}
アップデート: あなたが望むのが最初のテキストノードである場合、存在する場合は、クエリ理解の構文の代わりにLINQメソッド呼び出しを使用した例を次に示します。
var firstTextNode = p.Nodes().OfType<XText>().FirstOrDefault();
if (firstTextNode != null)
{
var textValue = firstTextNode.Value;
...do something interesting with the value
}
ノート: 使用 First()
また FirstOrDefault()
よりもパフォーマンスが高くなります Count() > 0
このシナリオで。 Count
常にコレクション全体を列挙します FirstOrDefault()
一致が見つかるまでのみ列挙します。
他のヒント
すべての価値を連結することができます XText
ノードイン parent
:
XElement parent = XElement.Parse(
@"<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
string result = string.Concat(
parent.Nodes().OfType<XText>().Select(t => t.Value));
// result == "HelloWorld!"
比較のために:
// parent.Value == "Hellotest1Worldtest2!"
// (parent.HasElements ? "" : parent.Value) == ""
Microsoftのどこかでコーダーが、すべてのテキスト値を連結した文字列と削除されていない文字列として返還することが役立つと考えたのは驚くべきことです。幸いなことに、別のMS開発者は、テキストノードの「浅い値」と呼ばれるものを返すためにXelement拡張機能を書きました ここ. 。ウィリーズがリンクをクリックしてから得られる人のために、関数は以下です...
public static string ShallowValue(this XElement element)
{
return element
.Nodes()
.OfType<XText>()
.Aggregate(new StringBuilder(),
(s, c) => s.Append(c),
s => s.ToString());
}
そして、あなたはそれをこのように呼びます。なぜなら、それはあなたにすべての白人も与えるからです
// element is a var in your code of type XElement ...
string myTextContent = element.ShallowValue().Trim();
MSDN 言う:
この要素のすべてのテキストコンテンツを含む文字列。複数のテキストノードがある場合、それらは連結されます。
したがって、動作は予想されます。
あなたはあなたの問題を解決することができます:
string textContent = parent.HasElements ? "" : parent.Value;
// Create the XElement
XElement parent = XElement.Parse(
@"<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
// Make a copy
XElement temp=new XElement(parent);
// remove all elements but root
temp.RemoveNodes();
// now, do something with temp.value, e.g.
Console.WriteLine(temp.value);