[英]Suppress xsi:nil but still show Empty Element when Serializing in .Net
[英]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.