Читать онлайн «C# для профессионалов. Том II». Страница 6

Автор Симон Робинсон

Теперь, когда атрибуты созданы и необходимо добавить другие элементы книги:

XmlElement newTitle=doc.CreateElement("title");

newTitle.InnerText="Case of the Missing Cookie";

newBook.AppendChild(newTitle);

Здесь снова создается новый объект на основе XmlElement (newTitle). Присваиваем свойству InnerText заголовок новой книги и добавляем потомок к элементу book. Затем это повторяется для остальных элементов book. Отметим, что элемент name добавлен как потомок элемента author. Это дает нам правильное отношение вложенности.

Наконец, мы добавляем элемент newBook к узлу doc.DocumentElement. Это тот же уровень, что и у всех других элементов book. Мы заменили существующий документ новым, в отличие от XmlWriter, где можно было только создать новый документ. Последнее, что нужно сделать, это записать новый документ XML на диск. В этом примере мы создаем новый XmlTextWriter и передаем его в метод WriteContentTo. Не забудьте вызвать метод Close на XmlTextWriter, чтобы сбросить содержимое внутренних буферов и закрыть файл. Методы WriteContentTo и WriteTo получают XmlTextWriter в качестве параметра. WriteContentTo сохраняет текущий узел и всех потомков в XmlTextWriter, в то время как WriteTo сохраняет текущий узел. Так как doc является объектом на основе XmlDocument, он представляет весь документ и поэтому будет сохранен. Можно было бы также использовать метод Save. Он всегда будет сохранять весь документ. Save имеет четыре перегружаемые версии. Можно определить строку с именем файла и путем доступа, объект на основе класса Stream, объект на основе класса TextWriter, или объект на основе XmlWriter. Именно это было использовано при выполнении примера. Отметим новую запись в конце списка:

Если нужно создать документ с самого начала, можно использовать класс XmlTextWriter. Можно также использовать XmlDocument. Какой из них выбрать? Если данные, которые желательно поместить в XML, доступны и готовы для записи, то самым подходящий будет класс XmlTextWriter. Однако, если необходимо создавать документ XML постепенно, вставляя узлы в различные места, то наиболее приемлемым будет применение XmlDocument. Вот тот же пример, который только что был рассмотрен, но вместо редактирования текущего документа мы создаем новый документ (DOMSample4):

private void button1_Click(object sender, System.EventArgs e) {

 // создать раздел объявлений

 XmlDeclaration newDoc=doc.CreateXmlDeclaration("1.0", null, null);

 doc.AppendChild(newDoc);

 // создать новый корневой элемент

 XmlElement newRoot=doc.CreateElement("newBookstore");

 doc.AppendChild(newRoot);

 // создать новый элемент 'book'

 XmlElement newBook=doc.CreateElement("book");

 // создать и задать атрибуты элемента "book"

 newBook.SetAttribute("genre","Mystery");

 newBook.SetAttribute("publicationdate", "2001");

 newBook.SetAttribute("ISBN", "123456789");

 // создать элемент 'title'

 XmlElement newTitle=doc.CreateElement("title");

 newTitle.InnerText="Case of the Missing Cookie";

 newBook.AppendChild(newTitle);

 // создать элемент author

 XmlElement newAuthor=doc.CreateElement("author");

 newBook.AppendChild(newAuthor);

 // создать элемент name

 XmlElement newName=doc.CreateElement("name");

 newName.InnerText="C. Monster";

 newAuthor.AppendChild(newName);

 // создать элемент price

 XmlElement newPrice=doc.CreateElement("price");

 newPrice.InnerText="9.95";

 newBook.AppendChild(newPrice);

 // добавить элемент 'book' к doc

 doc.DocumentElement.AppendChild(newBook);

 // записать на диск Note новое имя файла booksEdit.xml

 XmlTextWriter tr=new XmlTextWriter("..\\..\\..\\booksEdit.xml", null);

 tr.Formatting=Formatting.Indented; doc.WriteContentTo(tr);

 tr.Close();

 // загрузить заголовок в окно списка

 XmlNodeList nodeLst=doc.GetElementsByTagName("title");

 foreach(XmlNode node in nodeLst) listBox1.Items.Add(node.InnerText);

}


private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) {

 String srch="newBookstore/book[title='"+ listBox1.SelectedItem.ToString() + "']";

 XmlNode foundNode=doc.SelectSingleNode(srch);

 if (foundNode!=null) MessageBox.Show(foundNode.InnerText);

 else MessageBox.Show("Not found");

}

Заметим, что изменились только две начальные строки. Прежде чем сделать doc.Load, внесем новые элементы:

XmlDeclaration newDoc=doc.CreateXmlDeclaration("1.0", null, null);

doc.AppendChild(newDoc);

XmlElement newRoot=doc.CreateElement("newBookstore");

doc.AppendChild(newRoot);

Сначала создается новый объект XmlDeclaration. Параметрами являются версия (в настоящее время всегда "1.0"), кодировка (null подразумевает UTF-8) и, наконец, флаг standalone. Он может быть yes или no, но если вводится null или пустая строка, как в нашем случае, этот атрибут не будет добавляться при сохранении документа. Параметр кодировки должен задаваться строкой, которая является частью класса System.Text.Encoding, если не используется null.

Следующим создаваемым элементом станет DocumentElement. В данном случае мы называем его newBookstore, чтобы можно было видеть различие. Остальная часть кода является такой же, как и в предыдущем примере, и работает точно так же. Вот файл booksEdit.xml, создаваемый этим кодом:

<?xml version="1.0"?>

<newBookstore>

 <book genre="Mystery" publicationdate="2001" ISBN="123456789">

  <title>Case of the Missing Cookie</title>

  <author>

   <name>C. Monster</name>

  </author>

  <price>9.95</price>

 </book>

</newBookstore>

Мы не рассмотрели всех особенностей класса XmlDocument или других классов, способствующих созданию модели DOM в .NET. Однако мы видели мощь и гибкость, которые предлагает реализация DOM в .NET. Класс XmlDocument обычно используется, когда требуется случайный доступ к документу. Используйте классы на основе XmlReader, когда желательна модель потокового типа. Помните, что гибкость XmlDocument на основе XmlNode обеспечивается более высокими требованиями к памяти, поэтому подумайте тщательно о том, какой метод предпочтительнее в конкретной ситуации.

XPath и XslTransform

Мы рассмотрим XPath и XslTransform вместе, хотя они являются отдельными пространствами имен на платформе. XPath содержится в System.Xml.XPath, a XslTransform находится в System.Xml.Xsl. Причина совместного рассмотрения состоит в том, что XPath, в частности класс XPathNavigator, предоставляет ориентированный на производительность способ выполнения XSLTransform в .NET. Для начала рассмотрим XPath, а затем его использование в классах System.Xsl.

XPath

Пространство имен XPath создается для скорости. Оно позволяет только читать документы XML без возможностей редактирования. XPath создается для поверхностного выполнения быстрых итераций и выбора в документе XML. Функциональность XPath представляется классом XPathNavigator. Этот класс может использоваться вместо XmlDocument, XmlDataDocument и XPathDocument. Если требуются средства редактирования, то следует выбрать XmlDocument; при работе с ADO.NET будет использоваться класс XmlDataDocument (мы увидим его позже в этой главе). Если имеет значение скорость, то применяйте в качестве хранилища XPathDocument. Можно расширить XPathNavigator для таких вещей, как файловая система или реестр в качестве хранилища. В следующей таблице перечислены классы XPath с кратким описанием назначения каждого класса:

Имя класса Описание XPathDocument Представление всего документа XML. Только для чтения. XPathNavigator Предоставляет навигационные возможности для XPathDocument. XPathNodeIterator Обеспечивает итерацию по множеству узлов. Является эквивалентом для множества узлов в Xpath. XPathExpression Компилированное выражение Xpath. Используется SelectNodes, SelectSingleNodes, Evaluate и Matches. XPathException Класс исключений XPath.

XPathDocument не предлагает никакой функциональности класса XmlDocument. Он имеет четыре перегружаемые версии, позволяющие открывать документ XML из файла или строки пути доступа, объекта TextReader, объекта XmlReader или объекта на основе Stream.

Загрузим документ books.xml и поработаем с ним, чтобы можно было понять, как действует навигация. Чтобы использовать эти примеры, необходимо добавить ссылки на пространства имен System.Xml.Xsl и System.Xml.XPath следующим образом:

using System.Xml.XPath;