2017-06-28 4 views
2
<b> 
    <c> 
    <z> Wally </z> 
    <w> whatever </w> 
    </c> 
    <d> 
    <z> anotherValue </z> 
    </d> 
    <e> idValue </e> 
</b> 


class Example { 
    public string Id {get; set;} 
    public string name {get; set;} 
} 

上記のXMLとクラスがあるとします。私はLinQからXmlを使ってXMLからオブジェクトを作成しようとしています。私はこのようなものでこれを達成できる任意の点でnullになる可能性のある経路を指定するLinQ to xml

:これまでのところ

var doc = XDocument.Load(xmlPath); 
var root = doc.Root; 

var anExample = new Example() 
{ 
    Id = root.Element("e").Value, 
    name = root.Element("c").Element("z").Value 
}; 

とても良い、問題は「C」と「Z」のタグがオプションであることです。あなたは 'c'や 'c'を 'z'なしに持つことはできません。 次に、ヌルオブジェクトに対してElementメソッドとValueプロパティを呼び出さないように、これらのタグのそれぞれがヌルであるかどうかを確認しています。

var doc = XDocument.Load(xmlPath); 
var root = doc.Root; 

var anExample = new Example(){ Id = root.Element("e").Value }; 

var c = root.Element("c") 

if(c != null) { 
    var z = c.Element("z"); 
    if(z != null) 
    anExample.name = z.Value; 
} 

を入れ子レベルが増加するにつれて、物事は最悪の取得: は私が意味します。私は、私が欲しいことをするための最も良い方法があると思います。

答えて

1

あなたは、コールチェーン内のすべての項目がnullでないことを確認するためにC# 6.0 null-conditional operatorを使用することができます。

// C# 6 or higher: 
string value = doc.Root?.Element("c")?.Element("z")?.Value; 

のみ与えられた全ての要素が存在し、それ以外の場合nullする場合は、この式の結果が値を持っています。

もう1つの方法は、System.Xml.XPath名前空間のXPath拡張メソッドを使用して要素を見つけることです。それはヌル・条件演算子なしで良さそうに見えますので、あなたがC#6、あるいは古いバージョンを使用している場合には、より適している:

// C# 6 or higher: 
string value = doc.Root.XPathSelectElement("./c/z")?.Value; 

// C# 5 or lower: 
var element = doc.Root.XPathSelectElement("./c/z"); 
if (element != null) 
{ 
    string value = element.Value; 
} 

要素が存在しない場合XPathSelectElementnullを返しますので、結果は同じになります。

+0

この構文はC#6.0以降で使用できます(演算子 '?.')。 – Tatranskymedved

+1

@Tatranskymedvedこの素晴らしい修正をありがとう!私は私の答えを更新しました。 –

+0

ありがとうございます。私はxpathを避け、Linqだけに焦点を当てようとしています。 null条件付き演算子は私にとって最良の選択肢と思われます。 – ricky

0

最後の可能な瞬間までIEnumerableのLINQ世界に滞在しようとする必要があります。

これは、Elementの代わりにElementsを使用することを意味します。これは、要素がない場合は空のシーケンスを返します。

最後に、SingleOrDefaultを呼び出して結果の要素を取得するか、途中の要素の1つが欠落している場合はnullを呼び出すことができます。

要素をさまざまな種類に変換できるexplicit conversion operatorsがあります。これは、string以外に変換する必要がある場合や、要素がnullの場合も処理できる場合に便利です。

var name = (string) root.Elements("c").Elements("z").SingleOrDefault() 
+0

あなたの答えをありがとう。それは素晴らしいですが、値の代わりに 'z'の属性が必要な場合はどうなりますか? SingleOrDefault.Attribute( "attr")はエラーをスローします。 – ricky

+0

@rickyと 'Elements'には' Attributes'もあります。したがって、 'root.Elements(" c ")。Attributes(" z ")。SingleOrDefault()'。 –

+0

私はそれを知らなかった。 SingleOrDefault()?属性( "anAttr")。Value( "<">) ricky

関連する問題