在 Visual Studio 客户端应用程序中使用 xml 数据类型

后续版本的 Microsoft SQL Server 将删除该功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

利用 xml 数据类型可以存储 XML 片段,例如缺少单个顶级元素的 XML 实例以及 SQL Server 数据库中的有效 XML 文档。由于这种设计特征,xml 数据类型实例在 Visual Studio 2005 中必须映射到 System.Xml.XmlNode 数组,而不能作为 System.Xml.XmlDocument 返回。但它不支持分段的 XML。

直接使用 xml 数据类型实例值所包含的 XmlNode 数组时,您会注意到 InnerXmlOuterXml 成员属性在工作方式上的不同之处,尤其是当 xml 数据类型实例构成有效的 XML 文档时(例如,它具有单个顶级元素)。

例如,假设下列代码行将 SQL Server 端点 (MyServer.sql_endpoint) 的一个新实例作为 Web 代理启动,而 Web 代理有一个 Web 方法 (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>

如果 nodeArr[0] 的 InnerXml 和 OuterXml 属性然后被分配给一对字符串变量(xmlJustChildren 和 xmlWithRoot),如上面的代码所示,则 nodeArr[0].InnerXml 的值只包括当前元素(两个 <child/> 元素,但不是 <root> 元素本身)中包含的节点,而 nodeArr[0].OuterXml 将按预期方式工作:包括 XmlNodes 数组中的所有节点(<child/> 元素和 <root> 元素)。

如果更频繁地使用 XmlDocument,您会注意到此行为与您通常看到的不同,因为类实现 InnerXmlOuterXml 属性的方法不同。对于 XmlDocument 实例,文档实例作为文档中所有 XmlNodes 的包装元素。这包括顶级根节点和文档中可能包含的任何内联 DTD 或架构。因此,XmlDocument.InnerXml 的内容与 XmlDocument.OuterXml 的内容相同。

由于这些实现细节,在使用本机 XML Web 服务的客户端应用程序中,使用 System.Xml.XmlDocumentFragment 是使用 SQL Serverxml 数据类型实例的良好替代方法。习惯于使用 XmlDocument 的开发人员将更熟悉 XmlDocumentFragment 类,而且 XmlDocumentFragment 可以接受 XmlNode 数组而不会产生问题。

下列各节提供了代码,并概述了在客户端应用程序中如何将 XmlDocumentFragment 与 SQL Serverxml 数据类型实例值一起使用。

使用 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 通过字符串生成输入

以下示例说明了如何使用 XmlDocumentFragment 的 InnerXml 属性的字符串分配生成 XmlNode 的输入数组。

//  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 类有更多限制。以下示例显示了如何使用 System.Xml.XmlReader 从文件中填充 XmlDocumentFragment 实例。

//  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;