C#-操作XML笔记(补充中...)

本文介绍如何使用.NET框架中的DOM操作XML文件,包括读取、插入节点、查询节点、使用XPathNavigator进行高级操作以及序列化对象到XML。同时,文章还探讨了如何利用ADO.NET与XML的相互转换以及DiffGram的应用。

 

在.NET中使用DOM

XmlDocument doc 
= new XmlDocument();

doc.Load(
"books.xml");     

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

foreach (XmlNode node in nodeLst)

       listBox1.Items.Add(node.InnerText); 
// InnerXml / OuterXml

如何插入节点

XmlDocument doc 
= new XmlDocument();

doc.Load(
"books.xml");

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

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

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

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

 

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

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

newBook.AppendChild(newTitle);

 

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

newBook.AppendChild(newAuthor);

 

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

newName.InnerText 
= "Cookie Monster";

newAuthor.AppendChild(newName);

 

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

newPrice.InnerText 
= "9.95";

newBook.AppendChild(newPrice);

 

doc.DocumentElement.AppendChild(newBook);

 

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

tr.Formatting 
= Formatting.Indented;

//保存当前节点和子节点

doc.WriteContentTo(tr);

//只保存当前节点

//_doc.WriteTo(tr);

//_doc.Save(tr);

tr.Close();

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

foreach (XmlNode node in nodeLst)

       listBox1.Items.Add(node.InnerText); 

SelectSingleNode() 和SelectNodes() 都是在XmlNode中定义的,而XmlDocument是基于XmlNode的.

SelectSingleNode()返回一个XmlNode; SelectNodes()返回一个XmlNodeList;

XmlNode node 
= doc.SelectSingleNode("bookstore/book[title='VC深入浅出']");

XmlNodeList nodeLst 
= doc.SelectNodes("/bookstore/book/title");

如果要写入XML流的数据已经准备好,最好选择XmlTextWriter;如果只是建立XML文档的一小部分或是在不同的地方插入节点,最好用XmlDocument.希望有一个流类型的模型时,可以使用XmlReader;基于XmlDocument的XmlNode也能遍历XML,虽然灵活性高,但要求的内存较多;

 

 

XML和ADO.NET

将ADO.NET数据转换成XML文档

XmlDocument doc 
= new XmlDocument();

       MemoryStream memStrm 
= new MemoryStream();

       
//将数据表转换成XML,并放入内存流,使用流的好处是不需要将数据写入磁盘,并还能使用基本Stream类的其它对象.

       
//WriteXml重载方法中,其中一个方法需要一个XmlWriteMode的枚举参数;

       ds.WriteXml(memStrm, XmlWriteMode.IgnoreSchema);

       memStrm.Seek(
0, SeekOrigin.Begin);

       doc.Load(memStrm);

       
//936 = GB2312

       XmlTextWriter wrt 
= new XmlTextWriter("Product.xml", System.Text.Encoding.GetEncoding(936));

       wrt.Formatting 
= Formatting.Indented;

       doc.WriteContentTo(wrt);

XmlWriteMode枚举

成员名称
 说明
 
DiffGram
 作为 DiffGram 写入整个 DataSet,包括原始值和当前值。若要生成只包含已更改的值的 DiffGram,请调用 GetChanges,然后在返回的 DataSet 上作为 DiffGram 调用 WriteXml。 
 
IgnoreSchema
 以 XML 数据形式写入 DataSet 的当前内容,不带 XSD 架构。如果无数据加载到 DataSet 中,则不写入任何内容。 
 
WriteSchema
 以 XML 数据形式写入 DataSet 的当前内容,以关系结构作为内联 XSD 架构。如果 DataSet 只有架构而无数据,那么只写入内联架构。如果 DataSet 没有当前架构,则不写入任何内容。 
 

       上例中先将XML放入流,然后再调用WriteContentTo()方法写入磁盘,其实你也可以直接调用WriteXml()方法,直接

将XML文件写入磁盘. 如果你只需要将DataSet中的表架构转换成XML,那你可以使用 WriteXmlSchema() 方法.

ds.WriteXml(
"sample.xml", XmlWriteMode.WriteSchema);

       上例中,使用了XmlDocument的对象doc,不过将被转换后的XML读入doc的过程过于复杂,先要创建一个流,然后再调用WriteXml()方法写入流,最后再调用Load()方法.其实.NET已经提供了XmlDataDocument专门为XML和ADO.NET服务. XmlDocument的参数是一个DataSet的对象,实际上,如果没有参数,它还是会创建一个名为NewDataSet的DataSet,其中Tables中没有任何表,并且你还可以在创建后设置DataSet属性.

XmlDocument doc 
= new XmlDocument();

doc 
= new XmlDataDocument(ds);

如果DataSet中有多个表,并且表之间存在着Relations,怎么办
?其实,工作方式仍旧是酱紫.

ds.Relations.Add(ds.Tables[
"Client"].Columns["客户ID"],

                      ds.Tables[
"Order"].Columns["客户ID"]);    

       
//注意,此处生成的Product.xml是带有架构的         

ds.WriteXml(
"Product.xml", XmlWriteMode.WriteSchema);

将XML文档转换成ADO.NET数据

       ds.ReadXml(
"Product.xml");

       ReadXml()重载方法中,其中有方法需要用到XmlReadMode枚举(查问MSDN);如果你只需要读取架构,那可以直接调用ReadXmlSchema()方法.

 

 

使用XPathNavigator

XPathNavigator用于从XML文档中选择、迭代、编辑数据. 使用XPathDocument 创建XPathNavigator 对象,该对象为只读, 使用XmlDocument 创建XPathNavigator 对象,该对象为可编辑. XPathNavigator 对象的只读或可编辑状态是使用XPathNavigator 类的CanEdit 属性决定的。

//使用XPathDocument创建的对象只能处于只读状态

XPathDocument doc 
= new XPathDocument("books.xml");

// XPathNavigator包含了移动和选择所需元素的所有方法

XPathNavigator nav 
= ((IXPathNavigable)doc).CreateNavigator();

// XPathNodeIterator迭代器,由Select()方法返回,可以看作 XPath中的NodeList或NodeSet

XPathNodeIterator iter 
= nav.Select("/bookstore/book[@genre='novel']");

//MoveNext():移动到匹配XPath表达式的下一个节点上.但是,最初调用MoveNext()之后,定位在第一个节点上.

while (iter.MoveNext())

{

    
//SelectDescendants : 选择当前节点的子代节点中与选择条件匹配的所有子代节点。

XPathNodeIterator newIter 
= iter.Current.SelectDescendants(XPathNodeType.Element, false);

// MoveNext() :移动到匹配XPath表达式的下一个节点上,创建XPathNodeIterator

    
while (newIter.MoveNext())

        listView1.Items.Add(newIter.Current.Name 
+ "" + newIter.Current.Value);

}


如何像聚合函数一样,将所有书的价格相加
?

listView1.Items.Add(
"Total Cost = " + nav.Evaluate("sum(/bookstore/book/price)"));

如何插入节点
?

       XmlDocument doc 
= new XmlDocument();

       doc.Load(
"books.xml");

//XPathNavigator对象由XmlDocument对象创建,故处于可编辑状态

       XPathNavigator nav 
= doc.CreateNavigator();

if (nav.CanEdit)

{

XPathNodeIterator iter 
= nav.Select("/bookstore/book/price");

//MoveNext():移动到匹配XPath表达式的下一个节点上.但是,最初调用MoveNext()之后,定位在第一个节点上.

    
while (iter.MoveNext())

    
{

        
//在每一个<price> </price> 后面插入

        iter.Current.InsertAfter(
"<disc>5</disc>");

    }


}


doc.Save(
"newbooks.xml");

 

 

 

在XML中串行化对象

       System.Xml.Serialization命名空间中最重要的类是XmlSerializer.串行化一个对象,首先需要实例化一个XmlSerializer对象,并指定串行化的对象类型,然后实例化一个流
/写入器对象,把文件写入流/文档,最后调用Serializer()方法.

Product pd 
= new Product();

pd.ProductID 
= 200;

pd.CategoryID 
= 100;

pd.Discontinued 
= false;

pd.ProductName 
= "Serialize Objects";

……

XmlSerializer sr 
= new XmlSerializer(typeof(Product));

TextWriter tr 
= new StreamWriter("Product.xml");

//Serialize()方法有9个重载,但每一个方法都需要一个写入数据的流,可以是Stream,TextWriter或XmlWriter

sr.Serialize(tr, pd);

// XmlRootAttribute、XmlElementAttribute和XmlAttributeAttribute 是C#的属性,仅是一些声明信息,在运行

//期间由CLR获取.

// XmlRootAttribute把这个类,在串行化生成的XML文档中,标识为根元素

[System.Xml.Serialization.XmlRootAttribute()]

public class Product

{

    
private int prodId;

    
private string prodName;

    
private int suppId;

    ……

    
// 这里是XmlAttributeAttribute

    [XmlAttributeAttribute(AttributeName 
= "Discount")]

    
public int Discount

    
{

        
get return disc; }

        
set { disc = value; }

    }


    
// XmlElementAttribute把下面的成员看做一个XML元素

    [XmlElementAttribute()]

    
public int ProductID

    
{

        
get return prodId; }

        
set { prodId = value; }

    }


    [XmlElementAttribute()]

    
public string ProductName

    
{

        
get return prodName; }

        
set { prodName = value; }

    }


    [XmlElementAttribute()]

    
public int SupplierID

    
{

        
get return suppId; }

        
set { suppId = value; }

    }


}


 

Product.xml

<?xml version="1.0" encoding="utf-8"?>

<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Discount="0">

  
<ProductID>200</ProductID>

  
<ProductName>Serialize Objects</ProductName>

  
<SupplierID>1</SupplierID>

  
<CategoryID>100</CategoryID>

  
<QuantityPerUnit>6</QuantityPerUnit>

  
<UnitPrice>1000</UnitPrice>

  
<UnitsInStock>10</UnitsInStock>

  
<UnitsOnOrder>0</UnitsOnOrder>

  
<ReorderLevel>1</ReorderLevel>

  
<Discontinued>false</Discontinued>

</Product>

反串行化操作

Product newPd;

FileStream f 
= new FileStream("Product.xml", FileMode.Open);

XmlSerializer newSr 
= new XmlSerializer(typeof(Product));

//Deserialize()方法必须有一个流/读取器参数

newPd 
= (Product)newSr.Deserialize(f);

f.Close();

更为复杂的操作

       派生的类
+返回一个数据的属性

       可以看出,最后只需要串行化Inventory这个类,串行化它,就需要插入一个属性,该属性为每个要添加到数据中的类型包含一个XmlArrayItem构造函数(XmlArrayItem是由XmlArrayItemAttribute类表示的.NET属性名)

       XmlArrayItem构造函数的第一个参数是串行化过程中,XML中的元素名,如果不写,默认会与对象类型名相同;第二个参数是对象的类型;

public class Inventory

{

    
private Product[] stuff;

    
public Inventory() { }

    [XmlArrayItem(
"Prod"typeof(Product)),XmlArrayItem("Book"typeof(BookProduct))]

    
public Product[] InventoryItems

    
{

        
get return stuff; }

        
set { stuff = value; }

    }


}


public class BookProduct : Product

{

    
private string isbnNum;

    
public BookProduct() { }

    
public string ISBN

    
{

        
get return isbnNum; }

        
set { isbnNum = value; }

    }


}


 

private void button4_Click(object sender, EventArgs e)

{     

// XmlAttributes: 表示一个属性对象的集合

//第一步:创建一个XmlAttributes对象,为每个要重写的数据类型创建一个XmlElementAttribute对象

    XmlAttributes attrs 
= new XmlAttributes();    

    attrs.XmlElements.Add(
new XmlElementAttribute("Book"typeof(BookProduct)));

attrs.XmlElements.Add(
new XmlElementAttribute("Prod"typeof(Product)));

//第二步:创建XmlAttributeOverrides对象

XmlAttributeOverrides attrOver 
= new XmlAttributeOverrides();   

//本例中是要重写Inventory类中的InventoryItems成员 

    attrOver.Add(
typeof(Inventory), "InventoryItems", attrs);   

    Product newProd 
= new Product();

    BookProduct newBook 
= new BookProduct();

    newProd.ProductID 
= 100;

    newProd.ProductName 
= "Product Thing";

newProd.SupplierID 
= 10;

    newBook.ProductID 
= 101;

    newBook.ProductName 
= "How to Use Your New Product Thing";

    newBook.SupplierID 
= 10;

    newBook.ISBN 
= "123456789";

    Product[] addProd 
={ newProd, newBook };

    Inventory inv 
= new Inventory();

    inv.InventoryItems 
= addProd;

    TextWriter tr 
= new StreamWriter("Product.xml");

    XmlSerializer sr 
= new XmlSerializer(typeof(Inventory), attrOver);

    sr.Serialize(tr, inv);

    tr.Close();

    webBrowser1.Navigate(AppDomain.CurrentDomain.BaseDirectory 
+ "//inventory.xml");

}


 

       Product.xml

<?xml version="1.0" encoding="utf-8"?>

<Inventory xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  
<Prod Discount="0">

    
<ProductID>100</ProductID>

    
<ProductName>Product Thing</ProductName>

    
<SupplierID>10</SupplierID>

    
<CategoryID>0</CategoryID>

    
<UnitPrice>0</UnitPrice>

    
<UnitsInStock>0</UnitsInStock>

    
<UnitsOnOrder>0</UnitsOnOrder>

    
<ReorderLevel>0</ReorderLevel>

    
<Discontinued>false</Discontinued>

  
</Prod>

  
<Book Discount="0">

    
<ProductID>101</ProductID>

    
<ProductName>How to Use Your New Product Thing</ProductName>

    
<SupplierID>10</SupplierID>

    
<CategoryID>0</CategoryID>

    
<UnitPrice>0</UnitPrice>

    
<UnitsInStock>0</UnitsInStock>

    
<UnitsOnOrder>0</UnitsOnOrder>

    
<ReorderLevel>0</ReorderLevel>

    
<Discontinued>false</Discontinued>

    
<ISBN>123456789</ISBN>

  
</Book>

</Inventory>

 

读写DiffGram

DiffGram是包含数据在编辑对话前后的XML文档.大部分的DBMS都提供了跟踪或用于提交
/回滚过程的功能,但如果你使用的DBMS没有提供这些功能,就可以使用DiffGram.

保存带有DiffGram模式的XML文档

ds.Tables[
0].Rows[0]["产品名称"= "新改的";

DataRow dr 
= ds.Tables[0].NewRow();

dr[
"产品ID"= "1231234";

dr[
"产品名称"= "新加的";

ds.Tables[
0].Rows.Add(dr);

//首先需要保存为一个模式(架构)文件,是为读取DiffGram做准备

ds.WriteXmlSchema(
"author.xdr");

ds.WriteXml(
"authdiff.xml", XmlWriteMode.DiffGram);

使用DiffGram模式读取XML文档

DataSet ds 
= new DataSet();

//读取DiffGram的模式(架构)文件

ds.ReadXmlSchema(
"author.xdr");

ds.ReadXml(
"authdiff.xml", XmlReadMode.DiffGram);

 

author.xdr

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

<xs:schema id="XMLAuthors" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

  
<xs:element name="XMLAuthors" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

    
<xs:complexType>

      
<xs:choice minOccurs="0" maxOccurs="unbounded">

        
<xs:element name="Authors">

          
<xs:complexType>

            
<xs:sequence>

              
<xs:element name="产品ID" type="xs:int" minOccurs="0" />

              
<xs:element name="产品名称" type="xs:string" minOccurs="0" />

              
<xs:element name="单位数量" type="xs:string" minOccurs="0" />

              
<xs:element name="单价" type="xs:decimal" minOccurs="0" />

              
<xs:element name="库存量" type="xs:short" minOccurs="0" />

              
<xs:element name="订购量" type="xs:short" minOccurs="0" />

              
<xs:element name="再订购量" type="xs:short" minOccurs="0" />

              
<xs:element name="中止" type="xs:boolean" minOccurs="0" />

            
</xs:sequence>

          
</xs:complexType>

        
</xs:element>

      
</xs:choice>

    
</xs:complexType>

  
</xs:element>

</xs:schema>

 

authdiff.xml

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

<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">

  
<XMLAuthors>

    
<Authors diffgr:id="Authors1" msdata:rowOrder="0" diffgr:hasChanges="modified">

      
<产品ID>1</产品ID>

      
<产品名称>新改的</产品名称>

      
<单位数量>每箱24瓶</单位数量>

      
<单价>18.0000</单价>

      
<库存量>39</库存量>

      
<订购量>0</订购量>

      
<再订购量>10</再订购量>

      
<中止>true</中止>

    
</Authors>

    
<Authors diffgr:id="Authors2" msdata:rowOrder="1">

      
<产品ID>2</产品ID>

      
<产品名称>WaterBox</产品名称>

      
<单位数量>每箱24瓶</单位数量>

      
<单价>19.0000</单价>

      
<库存量>17</库存量>

      
<订购量>40</订购量>

      
<再订购量>25</再订购量>

      
<中止>false</中止>

</Authors>

......

    
<Authors diffgr:id="Authors70" msdata:rowOrder="69" diffgr:hasChanges="inserted">

      
<产品ID>1231234</产品ID>

      
<产品名称>新加的</产品名称>

    
</Authors>

  
</XMLAuthors>

  
<diffgr:before>

    
<Authors diffgr:id="Authors1" msdata:rowOrder="0">

      
<产品ID>1</产品ID>

      
<产品名称>苹果汁</产品名称>

      
<单位数量>每箱24瓶</单位数量>

      
<单价>18.0000</单价>

      
<库存量>39</库存量>

      
<订购量>0</订购量>

      
<再订购量>10</再订购量>

      
<中止>true</中止>

    
</Authors>

  
</diffgr:before>

</diffgr:diffgram>

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值