2009-09-01 7 views
2

を期待どおりがnil値を持つnillableな要素を持っている場合、あなたはこのようにそれをフォーマットすることになっている、nillableな要素を処理しません:LinqToXmlはW3C標準によると

<myNillableElement xsi:nil="true" /> 

をしかし、あなたは、このLinqToXmlステートメントを使用している場合...

element.Add(
    new XElement(ns + "myNillableElement", null); 

...結果のXMLが無効である... ...

<myNillableElement /> 

です。 MicrosoftのXML/XSDバリデーターによると、無効であるだけでなく、W3Cによると無効です。したがって、次にXMLを検証すると、エラーが発生します。

Nillable要素の正しい処理をオンにできるスイッチがいくつかありますか?

ありがとうございました。

答えて

3

XMLにLINQは、ほとんどいないスキーマを認識している - それはあなたがツリーを検証することができますが、それは派生しません。それからの特定のセマンティクス。あなたの間違いは、nullはどうにかして常にxsi:nilにマップされるべきだと考えています。 W3C仕様にはそのような要件はありません(むしろ、言語バインディングの種類をカバーしないため)。特に

、あなたが実際に呼び出すXElementコンストラクタは、子のリストであるタイプobject[]の引数を取る - それにnullを渡すとxsi:nilに何らかの関連性を持たなければならない理由はありません。どのような場合でも、LINQ to XMLは、あるスキーマに従って有効なXMLを生成していること、そしてこのスキーマの特定の要素の1つがnilled="true"であることを知っていると仮定していますか?

+0

あなたの答えをありがとう...私はあなたが私が観察したことは本当に間違った行動ではないことを私が確信しているので、私は記事のタイトルを編集すると思います。LinqToXmlのためのスキーマ対応のクラスセットがあったなら、それはいいでしょう。 – devuxer

1

うまくいけば、これは理想的な答えではありませんが、少なくともLinqToXmlのnillable要素を処理するのが少し簡単になるように、いくつかの拡張メソッドを書いています。

拡張メソッド:

public static class XElementExtensions 
{ 
    private static XName _nillableAttributeName = "{http://www.w3.org/2001/XMLSchema-instance}nil"; 

    public static void SetNillableElementValue(this XElement parentElement, XName elementName, object value) 
    { 
     parentElement.SetElementValue(elementName, value); 
     parentElement.Element(elementName).MakeNillable(); 
    } 

    public static XElement MakeNillable(this XElement element) 
    { 
     var hasNillableAttribute = element.Attribute(_nillableAttributeName) != null; 
     if (string.IsNullOrEmpty(element.Value)) 
     { 
      if (!hasNillableAttribute) 
       element.Add(new XAttribute(_nillableAttributeName, true)); 
     } 
     else 
     { 
      if (hasNillableAttribute) 
       element.Attribute(_nillableAttributeName).Remove(); 
     } 
     return element; 
    } 
} 

使用例

// "nil" attribute will be added 
element.Add(
    new XElement(NS + "myNillableElement", null) 
    .MakeNillable(); 

// no attribute will be added 
element.Add(
    new XElement(NS + "myNillableElement", "non-null string") 
    .MakeNillable(); 

// "nil" attribute will be added (if not already present) 
element.SetNillableElementValue(NS + "myNillableElement", null); 

// no attribute will be added (and will be removed if necessary) 
element.SetNillableElementValue(NS + "myNillableElement", "non-null string"); 
+0

これは望ましいことではない可能性がある、NULLとして空白の文字列を扱います。私。 'new XElement(" Name "、null)'と 'new XElement(" Name "、" ")'は 'nil'としてマークされます。 –

+0

@MattMitchell、興味深い点ですが、XElementを使ってヌル要素の値を表現することはできないため、この方法でコード化したと思います。 'new XElement(name、null)'を実行しても、 'Value'プロパティは' null'ではなく 'string.Empty'になります。したがって、文字列の場合、空と空とを区別する機能は失われますが、少なくとも値型(intなど)は期待通りに機能します。文字列の回避策が考えられる場合は、教えてください。 – devuxer

+0

'.SetNillableElementValue'の場合は、指定された' value'が 'null'かどうかを調べることができます。もしそうなら、nillable属性を追加します。あなたが言ったように、ソース値がnullであるかどうかを判断するための事実の後に(例えば 'MakeNillable'の場合)はありません。 –

2

また、null合体演算子を利用して、このような何かを行うことができます:

public static object Nil 
{ 
    get 
    { 
     // **I took a guess at the syntax here - you should double check.** 
     return new XAttribute(Xsi + "nil", true); 
    } 
} 

// ...... 

object nullableContent = ...; 
element.Add(
    new XElement(NS + "myNillableElement", nullableContent ?? Nil) 
    ); 
+0

非常に滑らかです!私は前に '? 'に出くわしていませんでした。しかし、属性を追加、削除、またはそのまま残す必要があるため、拡張メソッドはまだ 'SetElementValue'を処理する必要があると思います。 – devuxer

関連する問題