Мы с вами уже успели немного поговорить о том, как можно работать с XML-данными в приложениях, написанных на основе платформы Microsoft .NET. Сегодня продолжим этот разговор и посмотрим на некоторые более глубокие моменты.
Постановка задачи
Мы с вами, если вы, конечно же, помните, успели поговорить о том, как записывать и считывать данные в формате XML из файлов. Принципиально это ничем не отличается от передачи XML-данных, скажем, по какому-либо сетевому протоколу, поскольку в .NET для записи и считывания XML-данных используются потоки, и, соответственно, применив вместо файлового потока какой-либо другой, мы можем точно так же работать с XML-данными, просто из другого источника.
Однако запись и считывание XML - только вершина того айсберга кода, который может оказаться нужным написать в вашем приложении для работы с этим форматом. Помимо чтения и записи, самыми часто используемыми операциями являются валидация XML-документа и XSL-преобразование. Что это за операции?
Валидация нужна для того, чтобы проверить соответствие XML-документа определённым правилам его формирования, поскольку, сами понимаете, гораздо удобнее вынести из программы в отдельный текстовый файл описание формата для того, чтобы программный код был более гибким, и небольшие изменения файлового формата не вызывали необходимости переписывать заново программный код. Что касается XSLT (XSL-преобразования), то это нужно для того, чтобы быстро и просто переводить XML-данные в HTML. То есть, XSLT служит для отображения данных, хранящихся в XML-формате.
Эти две операции очень распространены, поскольку валидация данных и их XSL-трансформация используются в львиной доле web-приложений, написанных с использованием технологии XML. А потому, я так думаю, стоит рассказать об обеих этих действиях над данными в формате XML. Конечно, многое все ещё останется за кадром, так что вас ждёт третья часть этой статьи.
Валидация данных
Для начала поговорим о валидации данных. Для валидации данных используется класс XmlValidatingReader, который унаследован от предка использовавшегося нами для чтения данных класса XmlTextReader под названием XmlReader. Для валидации XML-данных могут использоваться различные описания XML-форматов, самые популярные из которых - DTD (Document Type Definition) и XML Schema. Поскольку я уже давно тому назад рассказывал читателям "Компьютерных вестей" о том, каким образом создаются документы в формате DTD и XML Schema (см. статью "XML - это всерьёз и надолго" в "КВ" №2'2007), то сейчас повторяться не буду. Кстати, хочу заметить, что, помимо DTD и XML Schema, в платформе .NET предусмотрена также поддержка XDR (XML-Data Reduced), а вот поддержки ещё одного аналога этих всех вещей, активно используемых разработчиками для валидации документов, RelaxNG, нет. Для того, чтобы проверять данные (см. предыдущую часть статьи), которые мы считываем из XML-файла, вы должны сначала сгенерировать DTD или Schema-документ, который затем будет использоваться приложением, которое мы с вами напишем. В Microsoft Visual Studio можно генерировать подобные документы автоматически, "скармливая" среде разработки XML-файлы. Но мне, к сожалению, придётся писать его руками, так как я использую не Visual Studio, а среду разработки #Develop (www.icsharpcode.com). Впрочем, не так уж важно, как именно вы сгенерируете схему для валидации XML-документов - самое важное состоит в том, чтобы эта схема вообще была и чтобы ваша программа её понимала.
Впрочем, довольно умных слов. Давайте, что ли, перейдём уже к программному коду, ради которого, собственно говоря, эта статья и затевалась.
string Sch = "c:\\demo.xsd"; String FileName = "c:\\demo.xml"; int i = 0; XmlTextReader xml= new XmlTextReader(FileName); xml.WhitespaceHandling = WhitespaceHandling.None; XmlValidatingReader validator = new XmlValidatingReader(xml); validator.Schemas.Add("",Sch); validator.ValidationType = ValidationType.Auto; while (validator.Read()){ if (validator.NodeType == XmlNodeType.Element){ if (validator.Name == " subelement "){ listBox1.Items.Add("subelement " + i + " found"); i++; while (validator.Read() && validator.Name == " subsubelement "){ listBox1.Items.Add(" " + xml.GetAttribute("attr")); } } } }
Ну а теперь, как водится, будем разбираться с каждой строчкой написанного программного кода. Сначала всё понятно - эти строки задают расположения файлов со схемой нашего XML-документа, которая будет использоваться для его валидации, сам документ собственной персоной и счётчик количества найденных элементов первого уровня (не корневых, а уровнем ниже), который уже должен быть знаком вам по считыванию XML-файлов безо всякой валидации. Затем мы создаём знакомый уже вам XmlTextReader и учим его разбираться с "пустотами" внутри XML-файла.
А вот дальше начинается интересное. Объект validator класса XmlValidatingReader используется для валидации документа. Мы добавляем схему (первый параметр в методе Add - это namespace URI, который используется для валидации через web, нам он сейчас не нужен). После этого мы говорим валидатору автоматически распознавать тип схемы (как я уже говорил выше, типы эти могут быть весьма разнообразными), а затем начинаем считывать элементы из XML-файла, который мы указали выше. Процесс чтения, в общем-то, мало отличается от того, который мы с вами изучали в первой части статьи, а потому особо заостряться на нём не будем.
В чём же состоит валидация? Если какие-то элементы XML-файла не будут соответствовать схеме, которая для него указана, будет сгенерировано исключение типа XmlException, которое нужно обрабатывать. Можно, конечно же, и не обрабатывать его никак, однако в таком случае будет выводиться сообщение об ошибке, которое, конечно, не порадует пользователей вашей программы. Можно ещё в качестве альтернативного способа повесить на валидатор обработчик события ValidationEventHandler, который тоже может использоваться для обработки ошибок несоответствия документа схеме.
XSL-преобразование
Для того, чтобы успешно применять XSL-преобразования к XML-документам, нужно, для начала, рассказать о том, что это самое преобразование собой представляет.
Как я уже говорил, XSLT позволяет использовать XML-данные для непосредственного рендеринга HTML-документов. Это очень удобно, поскольку позволяет программисту не отвлекаться на оформительские задачи и не зашивать эту часть жёстко в приложение, а выносить её отдельно в специальные файлы, которые легко доступны тем же, например, дизайнерам для изменения. Для того, чтобы описывать эти преобразования, которые совершаются над XML-документами, используется специальный язык разметки, основанный, конечно же, на всё том же XML. Называется этот язык Extensible Stylesheet Language, или, если короче, XSL. От его названия, как несложно догадаться, собственно, и пошло название самого XSL-преобразования.
Ниже будет приведён пример XSL-документа для того XML'а, который мы генерировали в первой части статьи, а ещё ниже будут даны разъяснения относительно того, что есть что в этом документе.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <xsl:output method="xml" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> <xsl:template match="rootelement/*"> <h1><xsl:value-of select="@attrib1"/></h1> <p> <xsl:value-of select="attrib2"/></p> <i><xsl:apply-templates/></i> </xsl:template> <xsl:template match="subsubelement"> <p> <xsl:value-of select="attr"/></p> </xsl:template> </xsl:stylesheet>
Вот такой занятный получился документик. Первая его строка - это стандартная для любого XML-документа строка, которая рассказывает всем заинтересованным людям и программам о том, что это документ не какой-нибудь позорный TXT, а полноценный XML со всеми вытекающими отсюда последствиями. Дальше идёт строка (вернее, несколько), сообщающая всем о том, что это, между прочим, и не просто XML, а XSL-документ, который может делать всё, что ему заблагорассудится, со всеми остальными XML-документами, которые только посмеют попасться на его пути. Если эти документы будут отвечать его спецификации, конечно же. Эта строка задаёт корневой элемент документа (напомню, что у XSL-документа, как и у всех приличных XML'ей, он может быть только один).
Далее идут элементы вида xsl:template. Они описывают реакцию той программы, которая будет производить XSLT-преобразование (да, то есть именно той программы, которую мы с вами и должны будем написать) на каждый из тегов, встречающихся в XML-файле, который должен быть преобразован. Для того, чтобы "вынимать" из тегов их атрибуты, в XSL-файле используется тег xsl:value-of, где в атрибуте select используется имя того атрибута, значение которого должно быть считано и подставлено в итоговый HTML-документ вместо всего этого тега. Остальные возможности XSL нам пока что, в общем-то, не понадобятся.
Кстати, стоит отметить, что механизм XSL весьма мощный и позволяет использовать для преобразования из XML в качестве итоговых форматов не только HTML. Очень часто одни XML-документы преобразуются в другие, и при этом нет необходимости писать какие-то специальные конвертеры. Так что теперь, когда и Microsoft Office, и OpenOffice.org имеют форматы документов, основанные на XML, конвертацию одного в другой можно, по всей видимости, осуществлять XSL-преобразованием.
Только вот о том коде, который будет заниматься этим самым преобразованием, мы с вами поговорить уже сейчас, к сожалению, не успеем, так что придётся отложить это на следующий раз.
Кстати, выяснилась и ещё одна любопытная деталь. Дело в том, что тот механизм валидации XML-документов, который я по старой памяти предложил вам, уже несколько устарел и в .NET Framework 2.0 и более новых версиях .NET'а не рекомендуется к использованию. Что ж, это, конечно, не очень хорошо, но лучше знать, как подойти к проблеме с разных сторон. А о том, как правильно работать с валидацией XML-файлов в новых версиях .NET Framework'а, я расскажу уже в следующий раз. Как и том, каким образом выполнять в .NET-приложениях XML-преобразования. Так что ждите новых номеров "Компьютерных вестей" с продолжением рассказа о работе с XML-данными в .NET-приложениях.
Вадим СТАНКЕВИЧ
Горячие темы