C#-操作XML




 
.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 用于从 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 >
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值