C#高级编程之处理XML-连载十四

时间:2010年04月12日 点击:106

23.8.1  ADO.NET数据转换为XML文档

下面要介绍的第一个示例使用ADO.NET、流和XMLNorthwind数据库中的一些数据推入DataSet,并从DataSet中加载带有XMLXmlDocument对象,把XML加载到列表框中。为了运行下面几个示例,需要添加如下using语句:

using System.Data;

using System.Xml;

using System.Data.SqlClient;

using System.IO;

因为要使用XmlDocument,所以还需要在模块级添加如下代码:

private XmlDocument doc = new XmlDocument();

对于ADO.NET示例,在窗体上添加一个DataGrid,这样就可以在ADO.NET DataSet中查看数据了,因为数据被绑定到网格上。还可以查看生成的XML文档中的数据,这些数据加载到了列表框中。下面是第一个示例的代码,它们在ADOSample1文件夹中:

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

{

   //create a dataset

   DataSet ds = new DataSet("XMLProducts");

   //connect to the northwind database and

   //select all of the rows from products table

   //make sure your login matches your version of SqlServer

   SqlConnection conn = new SqlConnection

               (@"server=GLYNNJ_CS\NetSDK;uid=sa;pwd=;database=northwind");

   SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Products",conn);

在创建了SqlDataAdapter对象da DataSet对象ds后,再实例化MemoryStreamStreamReader StreamWriter对象。StreamReader StreamWriter使用MemoryStream来浏览XML文档:

   MemoryStream memStrm=new MemoryStream();

   StreamReader strmRead=new StreamReader(memStrm);

   StreamWriter strmWrite=new StreamWriter(memStrm);

使用MemoryStream的原因是不必把数据写入磁盘。还可以使用基于Stream类的其他对象,例如FileStream。接着,填充DataSet,把它绑定到DataGrid上。DataSet中的数据现在应显示在DataGrid中:

   da.Fill(ds,"products");

   //load data into DataGrid

   dataGrid1.DataSource=ds;

   dataGrid1.DataMember="products";

下一步是生成XML。调用DataSet 类的WriteXml()方法,它生成一个XML文档。WriteXml有两个重载方法,一个重载方法的参数是带有文件路径和名称的字符串,另一个重载方法的参数是模式。这个模式是一个XmlWriteMode枚举,其值可以是

       IgnoreSchema

       WriteSchema

       DiffGram

如果不希望WriteXml方法把内联模式写入XML文件的开头,就使用IgnoreSchema,如果要写入内联模式,就使用WriteSchema。本节的后面介绍DiffGram

   ds.WriteXml(strmWrite,XmlWriteMode.IgnoreSchema);

   memStrm.Seek(0,SeekOrigin.Begin);

   //read from the memory stream to an XmlDocument object

   doc.Load(strmRead);

   //get all of the products elements

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

   //load them into the list box

   foreach(XmlNode nd in nodeLst)

     listBox1.Items.Add(nd.InnerText);

}

private void listBox1_SelectedIndexChanged(object sender,

                                           System.EventArgs e)

{

   //when you click on the listbox,

   //a message box appears with the unit price

   string srch="XMLProducts/products[ProductFTEL=" +

                         ' " '+ listBox1.SelectedItem.ToString() + ' " ' + "]";

   XmlNode foundNode=doc.SelectSingleNode(srch);

   if(foundNode!=null)

      MessageBox.Show(foundNode.SelectSingleNode("UnitPrice").InnerText);

   else

      MessageBox.Show("Not found");

}

23-9所示的屏幕图中,可以查看列表框中的数据和绑定的数据网格。

 23-9

如果只需要该模式,可调用WriteXmlSchema()而不是WriteXml()。这个方法有4个重载方法,第一个重载方法的参数是一个字符串,其中包含了XML文档的路径和文件名,第二个重载方法使用基于XmlWriter类的一个对象。第三个重载方法使用基于TextWriter类的对象。第四个重载方法派生于Stream类。

如果要把XML文档存入磁盘,就应执行下述操作:

string file = "c:\\test\\product.xml";

ds.WriteXml(file);

在磁盘上会生成一个格式正确的XML文档,并可以由另一个流、DataSet来读取,或者由另一个应用程序或网站使用。因为没有指定XmlMode参数,所以这个XmlDocument包含了模式。在本例中,把流作为XmlDocument.Load方法的参数。

准备好XmlDocument后,使用与前面一样的Xpath语句加载listbox。如果仔细查看,会发现listBox1_SelectedIndexChanged事件有了少许变化。它没有显示元素的InnerText,而是使用SelectSingleNode进行另一个XPath搜索,获得UnitPrice元素。所以每次单击列表框中的一个产品时,都会显示一个带有UnitPrice的消息框。现在数据有两个视图,但更重要的是,可以使用两个不同的模型来处理数据。可以使用System.Data命名空间来操纵数据,也可以使用System.XML命名空间来处理数据。这样应用程序就可以有某些非常灵活的设计,因为现在不必把一个对象模型绑定到程序上,这是ADO.NET System.Xml组合的强大之处。相同数据可以有多个视图,访问数据也有多种方式。

下一个示例去掉了3个流,使用内置于System.XML命名空间中的一些ADO功能简化了过程。但需要修改模块级的代码行:

private XmlDocument doc = new XmlDocument();

为:

private XmlDataDocument doc;

这么做的原因是现在使用的是XmlDataDocument。下面的代码在ADOSample2文件夹中:

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

{

   //create a dataset

   DataSet ds=new DataSet("XMLProducts");

   //connect to the northwind database and

   //select all of the rows from products table

   //make changes to connect string to match your login and server name

   SqlConnection conn=new SqlConnection

                (@"server=GLYNNJ_CS\NetSDK;uid=sa;pwd=;database=northwind");

   SqlDataAdapter da=new SqlDataAdapter("SELECT * FROM products",conn);

   //fill the dataset

   da.Fill(ds,"products");

   //load data into grid

   dataGrid1.DataSource=ds;

   dataGrid1.DataMember="products";

   doc=new XmlDataDocument(ds);

 

   //get all of the products elements

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

 

   //load them into the list box

   //we'll use a for loop this time

   for(int ctr=0;ctr<nodeLst.Count;ctr++)

      listBox1.Items.Add(nodeLst[ctr].InnerText);

}

可以看出,把DataSet加载到XML文档中的代码已经进行了简化。它没有使用XmlDocument类,而使用了XmlDataDocument类,这个类是为了使用DataSet对象的数据而专门设计的。

XmlDataDocument基于XmlDocument类,所以它拥有XmlDocument类的所有功能。一个主要区别是XmlDataDocument有重载的构造函数。注意下面的代码实例化了XmlDataDocument对象doc

doc = new XmlDataDocument(ds);

它的参数是我们创建的DataSet对象ds,从数据集中创建XML文档,而且不必使用Load方法。实际上,如果实例化一个新的XmlDataDocument对象时,不把DataSet作为参数,该XmlDataDocument就会包含一个名为NewDataSetDataSet,其表集合中没有任何DataTable,在创建了基于XmlDataDocument的对象后,还可以设置一个DataSet属性。

如果下面的代码添加到DataSet.Fill调用的后面:

ds.WriteXml("c:\\test\\sample.xml", XmlWriteMode.WriteSchema);

就会在文件夹C:\test中生成下面的XML文件:

<?xml version="1.0" standalone="yes"?>

<XMLProducts>

   <xs:schema id="XMLProducts" xmlns=""

              xmlns:xs="http://www.w3.org/2001/XMLSchema"

              xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

      <xs:element FTEL="XMLProducts" msdata:IsDataSet="true">

         <xs:complexType>

            <xs:choice maxOccurs="unbounded">

               <xs:element FTEL="products">

                  <xs:complexType>

                     <xs:sequence>

                        <xs:element FTEL="ProductID" type="xs:int"

                                    minOccurs="0" />

                        <xs:element FTEL="ProductName" type="xs:string"

                                    minOccurs="0" />

                        <xs:element FTEL="SupplierID" type="xs:int"

                                    minOccurs="0" />

                        <xs:element FTEL="CategoryID" type="xs:int"

                                    minOccurs="0" />

                        <xs:element FTEL="QuantityPerUnit" type="xs:string"

                                    minOccurs="0" />

                        <xs:element FTEL="UnitPrice" type="xs:decimal"

                                    minOccurs="0" />

                        <xs:element FTEL="UnitsInStock" type="xs:short"

                                    minOccurs="0" />

                        <xs:element FTEL="UnitsOnOrder" type="xs:short"

                                    minOccurs="0" />

                        <xs:element FTEL="ReorderLevel" type="xs:short"

                                    minOccurs="0" />

                        <xs:element FTEL="Discontinued" type="xs:boolean"

                                    minOccurs="0" />

                     </xs:sequence>

                  </xs:complexType>

               </xs:element>

            </xs:choice>

         </xs:complexType>

      </xs:element>

   </xs:schema>

   <products>

       <ProductID>1</ProductID>

       <ProductName>Chai</ProductName>

       <SupplierID>1</SupplierID>

        <CategoryID>1</CategoryID>

       <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>

       <UnitPrice>18</UnitPrice>

       <UnitsInStock>39</UnitsInStock>

       <UnitsOnOrder>0</UnitsOnOrder>

       <ReorderLevel>10</ReorderLevel>

       <Discontinued>false</Discontinued>

   </products>

</XMLProducts>

这里只显示了第一个Products元素。实际的XML文件应包含Northwind数据库中Products表的所有Products元素。

www.zdexe.com

赞助商链接

热门内容

相关内容

联系我们

联系方式