Поделиться через


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

В будущей версии Microsoft SQL Server эта возможность будет удалена. Избегайте использования этой возможности в новых разработках и запланируйте изменение существующих приложений, в которых она применяется.

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

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

Предположим, что имеются следующие строки кода, который создает новый экземпляр конечной точки SQL Server (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 — хорошая альтернатива для работы с экземплярами типа данных xmlSQL Server в клиентских приложениях, использующих веб-службы со встроенной поддержкой XML сервера. Класс 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 XmlDocumentSystem.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 XmlDtxmlnodes[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;