Разве анализаторы XML показывают разницу между xsi: nil = "true" и пропущенными элементами? - PullRequest
5 голосов
/ 03 января 2012

Могут ли синтаксические анализаторы / десериализаторы XML в целом определить разницу между нулевыми элементами, для которых явно задано нулевое значение, и необязательными элементами, которые не указаны ?

Предположим, что у нас есть следующий сложный тип:

<complexType name="NiceType">
  <sequence>
    <element name="niceElem" nillable="true" type="int" minOccurs="0" />
  </sequence>
</complexType>

Элемент явно имеет значение null (пример 1):

<niceType>
  <niceElem xsi:nil="true"/> 
</niceType>

Элемент опущен (пример 2):

<niceType>
</niceType>

Могут ли парсеры в целом, такие как реализации JAX-B или подобные .NET, такие как XML-модуль WCF, быть в состоянии определить разницу между примером 1 и примером 2 выше? Другими словами, могли бы вы совместимым образом объединить оба NULL-представления - как в примере - для передачи различных оттенков NULL?

1 Ответ

2 голосов
/ 03 января 2012

XML-парсеры (например, XmlReader, XmlDocument, XDocument) не обрабатывают xsi:nil специально - вы все еще видите элемент в потоке / документе.

XmlSerializer обрабатывает xsi:nil: в этом контексте это означает то же самое, что и пропущенный узел; Вы можете сделать сериализацию WCF, используя XmlSerializer, отметив DataContract s, используя XmlSerializerFormatterAttribute.

DataContractSerializer действительно использует атрибут: однако я не уверен, каковы все правила его использования (один случай - циклические ссылки ) - гораздо более вероятно, что элементы будут опущены. Я не думаю, что вам следует передавать xsi:nil на DataContractSerializer, если он не использует его в этом случае - поскольку DataContractSerializer разработан с учетом допущений для улучшения производительности де-сериализации.

Из spec похоже, что он изначально был разработан для работы как JavaScript null и undefined - где null (xsi:nil) является допустимым значением и undefined ( опущено) - полное отсутствие значения; особенно со сложными типами - вы можете предоставить элемент, но пропустить его содержимое (даже если содержимое требуется согласно схеме).

В общем, я бы этого избегал. Это не интуитивно понятно - я не думаю, что видел REST / SOAP API там, где он используется (кроме InfoPath, который использует его исключительно); большинство просто используют null = undefined. Объявление xmlns и его использование также потребляют несколько дополнительных ценных байтов.

Бонусные метки: Если вы сделаете элемент необязательным и не обнуляемым (например, xsd:int), генератор C # предоставляет свойство <Name>Specified - вы можете добавить свои собственные свойства, подобные этому. Это позволит вам различать xsi:nil и пропуск (ноль, если указано, и ноль, опускается, если не указано). Однако это работает только с XmlSerializer.

...