2015-04-21 4 views
1

В C# при обработке XML, который содержит элементы, которые определены в схеме как nillable="true", так и minOccurs="0", что является самым изящным решением рассказать элемент nil из пропущенного элемента?Обработка - Элемент xsi: nil vs. no element

Вариант использования - ситуация, когда служба получает XML-фрагмент, содержащий элементы, представляющие все поля изменяемой записи, но ни одно из полей, которые не были изменены.

Например, когда запись изменяется от { a: 1; b: 2; c: 3; } к { a: 1; b: 4; c: null }, служба может получить:

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

Когда запись изменений от { a: 1; b: 2; c: 3; } (идентичны) { a: 1; b: 4; c: 3 } (без изменений для «с»), услуги может получить:

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

Однако в C# эти два фрагмента с другим значением как карты на объект, который выглядит как { a: null; b: 4; c: null; }. При анализе XML информация о том, что c явным образом равна нулю или просто отсутствует, теряется. Мы не уверены в том, что для a и b необходимо установить значение null или оставить нетронутым.

В этом примере вы можете предположить, что сообщение должно содержать все поля, чтобы избежать путаницы (а также что-то, чтобы идентифицировать меняющуюся запись), но мы имеем дело с фактическими сообщениями о огромных записях, где необходимо только отправить актуальное. И мы имеем дело не только с целыми полями, но и со всеми типами простых и сложных типов.

Я считаю фрагменты XML довольно элегантными и понятными, но что является самым элегантным и понятным решением, которое вы предложили бы при их обработке в приложении C#?

+0

Я не получаю ваш 'minOccurs = 0' в вашем сообщении, вы можете привести пример и то, что он представляет? –

ответ

0

Предполагая, что вы используете XmlSerializer, вы можете добавить дополнительное логическое свойство помнить, является ли это свойство было явно задано. Кроме того, если свойство имеет имя 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> 

Как вы можете видеть, различие между нулевой собственностью и отключенной собственностью успешно сериализованный и десериализации.

Для получения дополнительной информации см. Здесь: MinOccurs Attribute Binding Support . (Документация описывает поддержку для общедоступных полей, но функциональность работает и для общедоступных объектов.)

0

Используя 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(); 
Смежные вопросы