Страница 4 из 7 Чтение документов с XmlValidatingReader XmlValidatingReader обеспечивает проверку допустимости XML-документов на основе трех схем: XML Schema definition language (XSD), XML-Data Reduced (XDR) schema и DTD. XmlValidatingReader наследован от класса XmlReader и используется объекты класса XmlTextReader для получения XML-документа. Тип схемы устанавливается значением свойства ValidationType. Если же передать этому свойству значение ValidationType.None, то проверка производится не будет. По умолчанию значение свойства ValidationType равно ValidationType.Auto и тип схемы определяется автоматически. В нашем примере мы используем схему XSD. Для ее создания мы загрузили в Visual Studio .NET XML файл с заказами, выбрали в контекстном меню пункты Create Schema, отметили как обязательные атрибуты дату и адрес для заказа и цену и название для товара и убрали значение из атрибута для целевого пространства имен. В итоге получился следующий XSD-файл. <?xml version="1.0" ?> <xs:schema id="Заказы" xmlns:mstns="https://tempuri.org/заказы.xsd" xmlns="https://tempuri.org/заказы.xsd" xmlns:xs="https://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified"> <xs:element name="Заказы" msdata:IsDataSet="true" msdata:Locale="ru-RU" msdata:EnforceConstraints="False"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="Заказ"> <xs:complexType> <xs:sequence> <xs:element name="Товар" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="Название" form="unqualified" type="xs:string" use="required" /> <xs:attribute name="Цена" form="unqualified" type="xs:string" use="required" /> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="Адрес" form="unqualified" type="xs:string" use="required" /> <xs:attribute name="Дата" form="unqualified" type="xs:string" use="required" /> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> Рассмотрим функцию, выполняющую проверку допустимости XML-документа с заказами на основе XSD-схемы. OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "Файлы XML (*.xml)|*.xml"; if (dlg.ShowDialog() != DialogResult.OK) return; string file = dlg.FileName; // получаем имя файла со схемой dlg.Filter = "Файлы XSD (*.xsd)|*.xsd"; if (dlg.ShowDialog() != DialogResult.OK) return; string schema = dlg.FileName; XmlValidatingReader readerVal = null; orders.Clear(); try { XmlTextReader reader = new XmlTextReader(file); reader.WhitespaceHandling = WhitespaceHandling.None; // пропускаем пустые узлы readerVal = new XmlValidatingReader(reader); readerVal.Schemas.Add("", schema); readerVal.ValidationType = ValidationType.Schema; readerVal.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandle); while (readerVal.Read()) if (readerVal.NodeType == XmlNodeType.Element) if (readerVal.Name == "Заказ") { Order order = new Order(readerVal.GetAttribute("Адрес"), DateTime.Parse(readerVal.GetAttribute("Дата"))); // получаем товары в заказе while (readerVal.Read() && readerVal.Name == "Товар") order.AddGood(readerVal.GetAttribute("Название"), float.Parse(readerVal.GetAttribute("Цена"))); orders.Add(order); } ShowOrders(); } catch (XmlException ex) { MessageBox.Show(ex.Message); } catch (Exception ex) { MessageBox.Show("Ошибка: " + ex.Message); } finally { if (readerVal != null) readerVal.Close(); } Вначале создаем объект XmlTextReader и передаем ему имя файла, указанное пользователем. Затем создаем XmlValidatingReader, который и будет отвечать за проверку допустимости документа. Затем добавляем XSD-схему из файла, указанного пользователем. Первым параметром в функции Add идет пространство имен (у нас передана пустая строка). Если же в вашем случае задано пространство имен, то его нужно определять из XSD-файла, получив значение атрибута targetNamespace у тега schema. Затем мы указываем тип схемы и определяем обработчик ValidationEventHandle события, который будет вызываться в случае возникновения ошибок или предупреждений. Тип события (ошибка или предупреждение) можно определить с помощью значения ValidationEventArgs.Severity, передаваемого обработчику. Также с помощью атрибутов можно получить дополнительную информацию об ошибке (ValidationEventArgs.Exception) и текстовое описание ошибки (alidationEventArgs.Message). Если мы не определим обработчик, то в случае определения недопустимости XML-документа будет возникать исключение XmlException, а предупреждения будут игнорироваться. На рисунке приведен диалог с сообщением об ошибке. Как и в случае в XmlTextReader мы в цикле вызываем метод Read для перебора всех узлов документа. Сам процес разбора документа так же ни чем не будет отличать от работы с XmlTextReader. |