关闭

C#-操作XML

712人阅读 评论(0) 收藏 举报



 
.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;基于XmlDocumentXmlNode也能遍历XML,虽然灵活性高,要求的内存较;
 
 
XMLADO.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专门为XMLADO.NET服务. XmlDocument的参数是一个DataSet的对象,实际上,如果没有参数,它还是会创建一个名为NewDataSetDataSet,其中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中的NodeListNodeSet
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,TextWriterXmlWriter
sr.Serialize(tr, pd);
// XmlRootAttributeXmlElementAttributeXmlAttributeAttributeC#的属性,仅是一些声明信息,在运行
//期间由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
<?xmlversion="1.0"encoding="utf-8"?>
<Productxmlns: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
<?xmlversion="1.0"encoding="utf-8"?>
<Inventoryxmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <ProdDiscount="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>
 <BookDiscount="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
<?xmlversion="1.0"standalone="yes"?>
<xs:schemaid="XMLAuthors"xmlns=""xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
 <xs:elementname="XMLAuthors"msdata:IsDataSet="true"msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choiceminOccurs="0"maxOccurs="unbounded">
        <xs:elementname="Authors">
          <xs:complexType>
            <xs:sequence>
              <xs:elementname="产品ID"type="xs:int"minOccurs="0" />
              <xs:elementname="产品名称"type="xs:string"minOccurs="0" />
              <xs:elementname="单位数量"type="xs:string"minOccurs="0" />
              <xs:elementname="单价"type="xs:decimal"minOccurs="0" />
              <xs:elementname="库存量"type="xs:short"minOccurs="0" />
              <xs:elementname="订购量"type="xs:short"minOccurs="0" />
              <xs:elementname="再订购量"type="xs:short"minOccurs="0" />
              <xs:elementname="中止"type="xs:boolean"minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
 </xs:element>
</xs:schema>
 
authdiff.xml
<?xmlversion="1.0"standalone="yes"?>
<diffgr:diffgramxmlns:msdata="urn:schemas-microsoft-com:xml-msdata"xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
 <XMLAuthors>
    <Authorsdiffgr:id="Authors1"msdata:rowOrder="0"diffgr:hasChanges="modified">
      <产品ID>1</产品ID>
      <产品名称>新改的</产品名称>
      <单位数量>每箱24</单位数量>
      <单价>18.0000</单价>
      <库存量>39</库存量>
      <订购量>0</订购量>
      <再订购量>10</再订购量>
      <中止>true</中止>
    </Authors>
    <Authorsdiffgr:id="Authors2"msdata:rowOrder="1">
      <产品ID>2</产品ID>
      <产品名称>WaterBox</产品名称>
      <单位数量>每箱24</单位数量>
      <单价>19.0000</单价>
      <库存量>17</库存量>
      <订购量>40</订购量>
      <再订购量>25</再订购量>
      <中止>false</中止>
</Authors>
......
    <Authorsdiffgr:id="Authors70"msdata:rowOrder="69"diffgr:hasChanges="inserted">
      <产品ID>1231234</产品ID>
      <产品名称>新加的</产品名称>
    </Authors>
 </XMLAuthors>
 <diffgr:before>
    <Authorsdiffgr:id="Authors1"msdata:rowOrder="0">
      <产品ID>1</产品ID>
      <产品名称>苹果汁</产品名称>
      <单位数量>每箱24</单位数量>
      <单价>18.0000</单价>
      <库存量>39</库存量>
      <订购量>0</订购量>
      <再订购量>10</再订购量>
      <中止>true</中止>
    </Authors>
 </diffgr:before>
</diffgr:diffgram>
 
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:245234次
    • 积分:3373
    • 等级:
    • 排名:第10000名
    • 原创:21篇
    • 转载:306篇
    • 译文:3篇
    • 评论:42条