簡體   English   中英

處理-元素xsi:nil與無元素

[英]Processing - Element xsi:nil vs. no element

在C#中,當處理包含在架構中定義為nillable="true"minOccurs="0"元素的XML時,從省略的元素中區分nil元素的最佳解決方案是什么?

用例是一種情況,其中服務接收到XML片段,該片段包含表示記錄的所有已更改字段的元素,而這些字段均未更改。

例如,當記錄從{ a: 1; b: 2; c: 3; } { a: 1; b: 2; c: 3; } { a: 1; b: 2; c: 3; }{ a: 1; b: 4; c: null } { a: 1; b: 4; c: null } { a: 1; b: 4; c: null } ,該服務可能會收到:

<change>
  <b>4</b>
  <c xsi:nil="true" />
</change>

當記錄從{ a: 1; b: 2; c: 3; } { a: 1; b: 2; c: 3; } { a: 1; b: 2; c: 3; } (相同)與{ a: 1; b: 4; c: 3 } { a: 1; b: 4; c: 3 } { a: 1; b: 4; c: 3 } (“ c”不變),該服務可能會收到:

<change>
  <b>4</b>
</change>

但是,在C#中,這兩個具有不同含義的片段都映射到一個看起來像{ a: null; b: 4; c: null; }的對象{ a: null; b: 4; c: null; } { a: null; b: 4; c: null; } { a: null; b: 4; c: null; } 解析XML時,有關c明確為nil或根本不存在的信息將丟失。 我們不確定a和b是否應將其設置為null或保持不變。

在此示例中,您可能建議消息應包括所有字段以避免混淆(以及用於標識更改記錄的內容),但是我們正在處理有關大型記錄的實際消息,其中僅需要發送實際的消息。相關。 我們不僅處理整數字段,還處理各種簡單和復雜類型。

我認為XML片段相當優雅和清晰,但是在C#應用程序中處理它們時,您建議的最優雅和清晰的解決方案是什么?

使用Linq-to-Xml,您可以解析字符串/流/文件,並確定元素節點是否包含值。

XElement change = XElement.Parse(string); // .Load(stream or file)
var changes = change.Elements()
                    .Where(x => (string)x != null)
                    // The above Where() determines your empty from non-empty
                    .Select(x => 
                    { 
                        Name = x.Name.LocalName, 
                        Value = (string)x 
                    })
                    .ToList();

假設您正在使用XmlSerializer ,則可以添加一個額外的Boolean屬性以記住是否已顯式設置屬性。 此外,如果該屬性具有名稱XXXSpecified ,其中XXX是相關的“真實”屬性的名稱,則XmlSerializer將在序列化時忽略該屬性。 例如:

public class TestClass
{
    string _value = null;

    [XmlElement("Value", IsNullable=true)]
    public string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            ValueSpecified = true;
        }
    }

    [XmlIgnore]
    public bool ValueSpecified { get; set; }

    public static void Test()
    {
        Test(new TestClass());
        Test(new TestClass() { Value = null });
        Test(new TestClass() { Value = "Something" });
    }

    static void Test(TestClass test)
    {
        var xml = test.GetXml();
        Debug.WriteLine(xml);
        var testBack = xml.LoadFromXML<TestClass>();
        Debug.Assert(testBack.Value == test.Value && testBack.ValueSpecified == test.ValueSpecified);
    }
}

這三個測試用例的XML輸出是:

 <TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> <TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Value xsi:nil="true" /> </TestClass> <TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Value>Something</Value> </TestClass> 

如您所見,null屬性和unset屬性之間的區別已成功序列化和反序列化。

有關更多信息,請參見此處: MinOccurs屬性綁定支持 (文檔描述了對公共字段的支持,但該功能也適用於公共屬性。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM