Информация схемы захвата при проверке XDocument - PullRequest
6 голосов
/ 22 октября 2011

Это похоже на вопрос C # Получение информации о схеме при проверке xml

Однако я работаю с XDocument для целей LINQ.

Я читаю /парсинг набора CSV-файлов и преобразование в XML, затем проверка XML по схеме XSD.

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

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

Я пытался получить доступ к SourceSchemaObject в аргументе ValidationEventArgs обработчика события Validation, но это всегда пусто.Я также попробовал GetSchemaInfo XElement, и он также имеет значение null.

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

Вот мой текущий метод проверки:

private List<String> this.validationWarnings;
private XDocument xDoc;
private XmlSchemaSet schemas = new XmlSchemaSet();

public List<String> Validate()
{
    this.validationWarnings = new List<String>();

    // the schema is read elsewhere and added to the schema set
    this.xDoc.Validate(this.schemas, new ValidationEventHandler(ValidationCallBack), true);

    return validationWarnings
}

А вот мой метод обратного вызова:

private void ValidationCallBack(object sender, ValidationEventArgs args)
{           
    var element = sender as XElement;

    if (element != null)
    {

        // this is a just a placeholder method where I will be able to extract the 
        //  schema information and put together a user friendly message for specific 
        //  validation errors    
        var message = FieldValidationMessage(element, args);

        // if message is null, then the error is not one one I wish to capture for 
        //  the user and is related to an invalid XML structure (such as missing 
        //  elements or incorrect order).  Therefore throw an exception
        if (message == null)
            throw new InvalidXmlFileStructureException(args.Message, args.Exception);
        else
            validationWarnings.Add(message);

    }
}

Строка var message = FieldValidationMessage(element, args); в моем методе обратного вызова является просто заполнителем и еще не существует. Цель этого метода - сделать 3 вещи:

  1. Определите конкретные ошибки проверки с помощью RegEx на args.Message (это уже работает, я протестировал шаблоны, которые планирую использовать)

  2. Получение значений атрибутов изXDocument, связанный с конкретным элементом XElement, который вызывает ошибку (например, номер строки и столбца в исходном CSV)

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

1 Ответ

6 голосов
/ 13 ноября 2011

Для любого, кто прочитает этот вопрос в будущем, мне удалось решить мою проблему, хотя и несколько иначе, чем я предлагал изначально.

Первая проблема, с которой я столкнулся, заключалась в том, что SchemaInfo как вValidationEventArgs и метод расширения GetSchemaInfo для XElement были равны нулю.Я решил это так же, как и в вопросе, который я изначально связал ....

List<XElement> errorElements = new List<XElement>();

serializedObject.Validate((sender, args) =>
{
    var exception = (args.Exception as XmlSchemaValidationException);

    if (exception != null)
    {
        var element = (exception.SourceObject as XElement);

        if (element != null)
            errorElements.Add(element);
     }

});

foreach (var element in errorElements)
{
    var si = element.GetSchemaInfo(); 

    // do something with SchemaInfo
}

Похоже, что информация о схеме не добавляется в XObject, пока ПОСЛЕ проверки обратного вызова проверки, поэтому, если вы попытаетесьчтобы получить доступ к нему в середине обратного вызова проверки, он будет нулевым, но если вы захватите элемент, то получите доступ, если после завершения метода Validate он не будет нулевым.

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

Я нашел этот вопрос после того, как задал свой оригинальный вопрос.Принятый ответ ссылается на действительно замечательную запись blog , которая разбивает объектную модель SchemaInfo.Мне потребовалось немного усилий, чтобы уточнить код в соответствии с моими целями, но он хорошо иллюстрирует, как получить SchemaInfo для любого элемента XmlReader (который я смог изменить для работы с XObject).

...