2012-08-09 1 views
2

ОК, поэтому здесь мы идем. У меня есть набор документов XML, которые я загружаю в свое приложение. В моем маленьком тесте я создал читателя, который проверяет схему, указанную XML-документом. Используя следующий код, он работает довольно хорошо.XDocument с встроенной схемой. SchemaInfo имеет значение

// Set the validation settings. 
XmlReaderSettings settings = new XmlReaderSettings(); 
settings.ValidationType = ValidationType.Schema; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); 

// Create the XmlReader object. 
XmlReader reader = XmlReader.Create("xml/note.xml", settings); 

// Load the XDocument from the reader 
XDocument loadedDoc = XDocument.Load(reader); 

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

Однако, если я хочу получить информацию о схеме о элементе, вызывая GetSchemaInfo() для указанного элемента, мне присваивается значение null. This question here говорит об использовании перегруженного метода проверки, но это не относится к этой ситуации, если только я чего-то не упускаю.

Возможно ли получить информацию о схеме, загруженную в XDoc, с использованием встроенной схемы или я должен делать это другим способом?

ответ

0

Отъезд my answer к моему собственному вопросу.

Первый абзац после блока кода является то, что важно для вас, но в основном, SchemaInfoбудет быть там, но это не добавляется до после проверка обратного вызова.

Обходной я использовал в основном это (Примечание: этот код был протестирован и работает при загрузке XML непосредственно и вызова XDocument.Validate на XmlSchemaSet, но помещение должно быть таким же или с XmlReader и встроенными схемами):

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 element in errorElements 
{ 
    var si = element.GetSchemaInfo; 

    // do something with SchemaInfo 
} 

Я только пытался захватить SchemaInfo для элементов, следовательно, as произнесения и нулевой чек, но это должно работать для других типов узлов, как Attributes (не тестировался, хотя, так что я мог бы быть неправильно).

Если вы хотите использовать определенный метод обратного вызова вместо анонимного делегата, то ваш errorElements должен быть полем уровня класса, и вы можете делать то, что вам нужно сделать после завершения проверки (опять же, я добавит в непроверенный тег).

public class SomeClass 
{ 

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

    public void Load() 
    { 

     // Set the validation settings. 
     XmlReaderSettings settings = new XmlReaderSettings(); 
     settings.ValidationType = ValidationType.Schema; 
     settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; 
     settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
     settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
     settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
     settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); 

     // Create the XmlReader object. 
     XmlReader reader = XmlReader.Create("xml/note.xml", settings); 

     // Load the XDocument from the reader 
     XDocument loadedDoc = XDocument.Load(reader); 

     // do something with errorElements 

    } 

    public void ValidationCallBack(object sender, ValidationEventArgs e) 
    { 
     var exception = (args.Exception as XmlSchemaValidationException); 

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

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

    } 

} 

В ответ на ваш комментарий о желании в IXSchemaInfo для всех узлов, информация схемы добавляется к XElement после проверки, независимо от того, удался или прошел узел, поэтому ваше требование фактически будет легче, так как вам не нужно сохранять список неудачных узлов. Вы должны быть в состоянии сделать это:

public void Load() 
{ 

    // Set the validation settings. 
    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.ValidationType = ValidationType.Schema; 
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; 
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
    settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); 

    // Create the XmlReader object. 
    XmlReader reader = XmlReader.Create("xml/note.xml", settings); 

    // Load the XDocument from the reader 
    XDocument loadedDoc = XDocument.Load(reader); 

    foreach (var node in loadedDoc.Descendants()) 
    { 
     var si = node.GetSchemaInfo(); 
    } 

} 

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

+0

Спасибо за ответ, я не могу проверить, как я далеко от своей машины разработки, но сделаю это как можно скорее. Однако, глядя на код, кажется, что он будет работать только для узлов с ошибками. То, к чему я стремился, было загрузить всю информацию о схеме, желательно для документов, которые проходят проверку. Мы собираемся использовать эту информацию для некоторой динамической сериализации позже. – djstamp

+0

Этот точный код будет работать только с узлами с ошибками, так как вы только собираете 'XElement' в обратном вызове проверки, но' SchemaInfo' должен присутствовать * после того, как * проверка завершена для всего, поэтому вы можете попробовать в этот момент (я добавлю еще один пример). – psubsee2003

+0

К сожалению, использование GetSchemaInfo для элементов, загруженных таким образом, возвращает null. Единственный способ, которым я смог получить информацию о схеме, загруженную для всего документа, - это использовать перегруженный метод проверки, упомянутый в вопросе, на который я ссылался первоначально. Похоже, что если я хочу получить доступ ко всей информации о схеме, мне нужно будет загрузить и проверить мои документы таким образом. Не невозможно, просто не идеально. Спасибо за помощь. Любые другие идеи приветствуются! – djstamp

Смежные вопросы