Проверка данных С# по XSD с указанием места ошибки

У меня есть классы, сгенерированные из схемы xsd с помощью xsd.exe. У меня нет контроля над схемой. Чтение, запись с помощью XmlSerlializer и проверка сериализованных данных работают нормально. Я хотел бы реализовать онлайн-проверку ошибок для моих данных, включая пользовательский ввод, на основе правил в схеме. Опять же, у меня нет проблем с сериализацией и проверкой, но тогда я не вижу простого способа отследить местонахождение ошибки, в каком экземпляре какого класса она произошла. Я нашел комментарий, в котором упоминается, что причина отсутствия XmlValidatingWriter заключается в том, что классы уже должны обеспечивать совместимость схемы, однако это неверно для классов, сгенерированных xsd.exe. (структура и типы хороши, но уникальные поля, совпадения шаблонов и т. д. не рассматриваются) Существует страница о Проверка XmlSchemaValidator на основе push, но мне это кажется очень ручным, полностью игнорируя тот факт, что все мои классы сериализуемы в xml.

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

Спасибо.


person Marsupilami    schedule 26.08.2017    source источник
comment
Большинство экземпляров XmlReader реализуют IXmlLineInfo. XElement также реализует это. В зависимости от того, как вы проверяете свой XML, вы можете использовать его для извлечения местоположения ошибки по строкам этого ответа или вот этот. Можете ли вы отредактировать свой вопрос, чтобы поделиться минимальный воспроизводимый пример, показывающий, как вы проверяете свой XML?   -  person dbc    schedule 26.08.2017
comment
Кроме того, XmlSchemaException содержит информацию о линии и позиции. Это прямо здесь, в XmlReaderSettings.ValidationEventHandler так что вы должны быть готовы к работе.   -  person dbc    schedule 26.08.2017
comment
См. также Могу ли я не выполнить десериализацию с помощью XmlSerializer в C#, если элемент не найден? для универсального метода проверки во время десериализации . Ошибки проверки будут переданы ValidationEventArgs, содержащий XmlSchemaException.   -  person dbc    schedule 26.08.2017
comment
@dbc, спасибо. Я могу это сделать, но меня не очень интересует, где ошибка в сериализованных данных (строка/позиция). Меня волнует, где он находится в моей иерархии объектов до сериализации. Мне интересно, есть ли способ получить LineInfo во время сериализации, что говорит мне, когда XmlWriter записывает один из моих объектов в поток, в какой строке он оказался. Таким образом, по крайней мере, я мог отследить точный объект на основе строки в XmlSchemaException или в обработчике событий.   -  person Marsupilami    schedule 26.08.2017
comment
Кстати, я использую XDocument.Validate после сериализации. Но я не думаю, что это имеет значение.   -  person Marsupilami    schedule 26.08.2017


Ответы (1)


Хорошо, вот что я в итоге сделал. Я не горжусь этим.

  1. У меня есть базовый класс, от которого наследуются все мои узлы xml. Я добавил к нему свойство GUID, которое помечено как xmlattribute и по умолчанию имеет атрибут xmligore, чтобы оно не участвовало в обычной сериализации/десериализации.
  2. Когда я собираюсь сериализовать для проверки, я создаю xmlattributesoverride, чтобы избавиться от xmignore свойства GUID. Руководство будет сериализовано в атрибут xml каждого элемента.
  3. Я создаю новый XDocument и сериализую в него.
  4. Я запускаю XDocument.Validate, используя схему, которую мне нужно проверить.
  5. В обработчике событий проверки я игнорирую все ошибки, которые жалуются на дополнительный атрибут guid.
  6. Когда я получаю реальную ошибку проверки или предупреждение, я могу найти фактический объект, который был сериализован в этот конкретный элемент на основе guid.
  7. Выгода.

Вероятно, очень неэффективно, но для размера данных, с которыми я работаю, все в порядке.

person Marsupilami    schedule 28.08.2017