Работа с типом данных xml в клиентских приложениях Visual Studio

Тип данных xml в SQL Server 2005 позволяет хранить в базе данных SQL Server фрагменты XML-документов, например экземпляры XML, в которых нет единого корневого элемента, а также допустимые XML-документы. Из-за этих архитектурных особенностей экземпляры типа данных xml в Visual Studio 2005 должны сопоставляться с массивом элементов System.Xml.XmlNode, а не возвращаться как объект класса System.Xml.XmlDocument. Этот класс не поддерживает работу с фрагментами XML.

При работе напрямую с массивом объектов XmlNode, хранящихся в значении типа данных xml, обнаружатся различия между работой свойств класса InnerXml и OuterXml, особенно когда экземпляр типа данных xml образует допустимый XML-документ, то есть у него есть единый корневой элемент.

Предположим, что имеются следующие строки кода, который создает новый экземпляр конечной точки SQL Server 2005 (MyServer.sql_endpoint) как веб-прокси с веб-методом (GetSomeXml), возвращающим строку с экземпляром типа данных xml.

MyServer.sql_endpoint proxy = new MyServer.sql_endpoint();
proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
SqlXmlDt = proxy.MyServerdboGetSomeXml();
System.Xml.XmlNode[] nodeArr = SqlXmlDt.Any;
string xmlJustChildren = nodeArr[0].InnerXml;
string xmlWithRoot = nodeArr[0].OuterXml;

Строка типа данных xml со значением будет содержать такие данные:

<root><child/><child/></root>

Если свойства InnerXml и OuterXml массива nodeArr[0] затем присваиваются паре строковых переменных (xmlJustChildren и xmlWithRoot), как в приведенном коде, окажется, что значение nodeArr[0].InnerXml будет содержать только узлы внутри текущего элемента (оба элемента <child/>, но не сам элемент <root>), а nodeArr[0].OuterXml будет работать, как ожидалось: он будет содержать все узлы из массива XmlNodes (элементы <child/> и элемент <root>).

Обратите внимание на то, что это поведение отличается от более привычного поведения XmlDocument, так как этот класс реализует свойства InnerXml и OuterXml по-другому. В экземплярах XmlDocument экземпляр документа играет роль упаковщика для всех элементов XmlNodes документа. Сюда входят и корневой узел, и все встроенные определения DTD или схемы, которые могут быть включены в документ. Поэтому содержимое XmlDocument.InnerXml не отличается от содержимого XmlDocument.OuterXml.

Из-за этих особенностей реализации использование класса System.Xml.XmlDocumentFragment — хорошая альтернатива для работы с экземплярами типа данных xml SQL Server в клиентских приложениях, использующих веб-службы со встроенной поддержкой XML сервера SQL Server 2005. Класс XmlDocumentFragment будет более знаком разработчикам, работавшим только с XmlDocument, и XmlDocumentFragment принимает массив элементов типа XmlNode без каких-либо проблем.

В следующих разделах приведен код и обзор использования класса XmlDocumentFragment для работы со значениями SQL Server типа xml в клиентских приложениях.

Обработка вывода с помощью класса XmlDocumentFragment

Следующий код показывает, как можно поместить массив элементов XmlNode в объект XmlDocumentFragment, а затем выбрать узлы из этого фрагмента с помощью выражения XPath.

System.Xml.XmlDocumentFragment fragOut = SqlXmlDt.Any[0].OwnerDocument.CreateDocumentFragment();

//  Loop over your XmlNode array and populate your XmlDocumentFragment.
foreach (System.Xml.XmlNode xmlnode in SqlXmlDt.Any)
{
    fragOut.AppendChild(xmlnode);
}

//  Loop over your XPath expression/selection for results.
foreach (System.Xml.XmlNode xmlpath in fragOut.SelectNodes("//bar"))
{
    System.Console.WriteLine(xmlpath.OuterXml);
}

Построение ввода из строки с помощью класса XmlDocumentFragment

Следующий код демонстрирует, как построить массив элементов XmlNode для ввода, присваивая строку свойству InnerXml объекта XmlDocumentFragment.

//  Create an owning XmlDocument
System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument();

//  Create your XmlDocumentFragment.
System.Xml.XmlDocumentFragment fragIn = xmldoc.CreateDocumentFragment();

//  Fill the XmlDocumentFragment with a string.
fragIn.InnerXml =
"  <a>" +
"    <b>inputvalue</b>" +
"  </a>" +
"  topstuff" +
"  <b/>";

//  Create an XmlNode array (should never require more than one element).
System.Xml.XmlNode[] xmlnodes = new System.Xml.XmlNode[1];

//  Put the XmlDocumentFragment in the array and fill your XmlDt
xmlnodes[0] = (System.Xml.XmlNode) fragIn;
SqlXmlDt.Any = xmlnodes;

Построение ввода из файла с помощью класса XmlDocumentFragment

Когда дело касается наполнения экземпляра, класс XmlDocumentFragment более ограничен, чем XmlDocument. Следующий пример показывает, как наполнить экземпляр класса XmlDocumentFragment из файла с помощью System.Xml.XmlReader.

//  Create an owning XmlDocument.
System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument();

//  Create your XmlDocumentFragment.
System.Xml.XmlDocumentFragment fragIn = xmldoc.CreateDocumentFragment();

//  Build an XmlReader from the file.
System.Xml.XmlReaderSettings rs = new System.Xml.XmlReaderSettings();
rs.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;
System.Xml.XmlReader reader = System.Xml.XmlReader.Create("c:\\file.xml", rs);

//  Populate the fragment with the nodes from the XmlReader.
System.Xml.XmlNode child;
while (null != (child = xmldoc.ReadNode(reader)))
     fragIn.AppendChild(child);

//  Create your XmlNode array (should never require more than one element)
    System.Xml.XmlNode[] xmlnodes = new System.Xml.XmlNode[1];

//  Put the XmlDocumentFragment in the array and fill our XmlDt.
xmlnodes[0] = (System.Xml.XmlNode) fragIn;
SqlXmlDt.Any = xmlnodes;

См. также

Другие ресурсы

Запрос XQuery к типу данных xml
Написание клиентских приложений

Справка и поддержка

Получение помощи по SQL Server 2005