• XML on Windows Mobile (C#)


     

    XML on Windows Mobile (C#)

     

    http://msdn.microsoft.com/zh-tw/dd327595(zh-cn).aspx

     

    作者:黄季冬

    时间:2008-02-16

    摘要

    Windows Mobile 上的XML 相关类,并利用它们高效地操作XML 文件( )

    Keywords

    .Net Compact Framework, Windows Mobile, XML

     

    两年以前张欣同学曾经做过一期Webcast 谈到了这相关的内容,详见:

    http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032328201&EventCategory=3&culture=zh-CN&CountryCode=CN

    本文主要涉及一些Webcast 里面没有说到的东西, 关于XML 本身的语法和用法我就不在此赘述了,首先,我们来看一看.NET Compact Framework System.XML 这个命名空间下,为我们操作XML 提供了哪些类型支持:

    类名

    说明

    XmlReader

    抽象类,提供了快速,单向,只读的读取XML 文件流操作

    XmlWriter

    抽象类,为生成一个XML 文件流提供了接口

    XmlTextReader

    继承于XmlReader ,用于格式良好的XML 文本处理

    XmlTextWriter

    XmlWriter 的一个实现类

    XmlNodeReader

    公共类,用于处理内存中的XML DOM Tree

    XmlNodeWriter

    公共类,用于在内存中产生XML DOM Tree

    XmlDocument

    一个XML DOM Tree 的模板类

    呃,先来看那个名字跟其他几个类不太一样的吧:XmlDocument.

    XmlDocument 用于把XML 文件加载到内存中间。调用Load() 方法即可将XML 文件作为一个数据树加载到内存。Load() 方法提供了几个重载,你可以通过文件名,任意流,或从XmlReader 继承的类以及System.IO.StreamReader TextReader Load 。这里需要区别一下的是另一个方法LoadXml() ,它是用来加载Xml 字符串的,而不是文件!

    下面的例子是从XmlTextReader Load 一个XML 文件:

    XmlDocument xmldoc = new XmlDocument();
    XmlTextReader xmlRdr = new XmlTextReader(@""Storage Card"books.xml");
    xmlRdr.WhiteSpaceHandling = WhiteSpaceHandling.None;
    xdoc.Load(xmlRdr);

    这里提到了XmlTextReader 这个类,可以说XmlTextReader XmlReader 在细粒度控制方面的一个实现。XmlTextReader 包含了当前节点的位置信息。调用它的Read() 方法,讲从文件中读取下一个节点的信息,读取顺序是深度优先的。通常,在读取数据之初,我们会调用MoveToContent() 去跳过一些非数据的元素段,直接到达根节点处,调用Skip() 方法会跳过当前界点的所有分节点,这在检索节点的时候可能会用得到,可以跳过一些不必要的子节点而节约一点性能,但是对设备上小规模的XML 文件,这个效果往往不是太明显。不过显然可以理解,这种不需要加载整个文件的单向的读写方式,要比使用XmlDocument 对象要快得多~

    说到性能,对于资源有限的设备来说,这显然是不可忽略的一点,在操作XML 的时候,我们也应考虑到这一点,在使用XmlReader XmlWriter 的时候,可以使用XmlReaderSettings XmlWriterSettings 来调整性能,例如使用IgnoreWhiteSpace 来忽略空白字符,或着使用IgnoreComments 来忽略注释行等等,

    另外需要注意的是,如果我们使用XmlReader 来读取的时候要避免使用Schema ,因为在单向读取的时候,Schema 的校验会损失一部分性能,而用DataSet 来读取的时候,尽量使文件包含Schema 来确定表结构,这样读起来会比较快,不需要编译器来为Dataset 创建架构。

    从细粒度方面考虑,可以用MoveToAttribute() 来设置XmlReader 的访问点,访问各个属性。例如

    public void ShowAttributes(XmlReader reader)

            {

                if (reader.HasAttributes)

                {

                    Console.WriteLine("Attributes of <" + reader.Name + ">");

                    for (int i = 0; i < reader.AttributeCount; i++)

                    {

                        reader.MoveToAttribute(i);

                        Console.WriteLine(reader.Name + "::" + reader.Value);

                    }

                    reader.MoveToElement(); //属性访问完毕后让reader返回到元素节点上来

                }

            }

    XmlNodeReader XmlNodeWriter XmlNode 提供了快速非缓存的访问方式,可以直接从Xml Stream 获取信息。

    好,再来看一个例子

    <bookstore>

     <book Section=" XML" PublicationDate="2004" ISBN="0-7645-7077-3">

        <title>Beginning XML, 3rd Edition</title>

        <author>

          <first-name>David</first-name>

          <last-name>Hunter</last-name>

        </author>

        <price>39.99</price>

     </book>

     <book Section=" Java" PublicationDate="2004" ISBN="0-7645-6874-4">

        <title>Ivor Horton's Beginning Java 2, JDK 5 Edition</title>

        <author>

          <first-name>Ivor</first-name>

          <last-name>Horton</last-name>

        </author>

        <price>49.99</price>

     </book>

     

     <book Section=" Database" PublicationDate="2005" ISBN="0-7645-7950-9">

        <title>Beginning MySQL</title>

        <author>

          <first-name>Robert</first-name>

          <last-name>Sheldon</last-name>

        </author>

        <author>

          <first-name>Geoff</first-name>

          <last-name>Moes</last-name>

        </author>

        <price>39.99</price>

     </book>

    </bookstore>

    1) 使用XmlTextReader

    这个XML 文件包含了几本书(book) 的相关信息,书有分元素title author prize 和属性Section PublicationDate ISBN 。我现在想做的事情就是把这个XML 文件的内容按照我预定的格式打印出来,并存放到一个output.txt 文本文件里面:

    首先,我们定义两个用于读写的reader writer

    XmlTextReader reader = null;
    StreamWriter writer = null;

    在处理函数里面,首先我们做一个初始化:

    writer = newStreamWriter(@""Storage Card"output.txt",false);
    reader = newXmlTextReader(@""Storage Card"books.xml");

    reader 在读的时候

    while (reader.Read())

    {

        //XmlNodeType这个枚举让我们方便的对不同类型的节点进行相应的操作

        switch (reader.NodeType)

        {

            caseXmlNodeType.XmlDeclaration:

                FormatOutput(writer, reader, "XmlDeclaration");

                break;

            caseXmlNodeType.ProcessingInstruction:

                FormatOutput(writer, reader, "ProcessingInstruction");

                break;

            caseXmlNodeType.DocumentType:

                FormatOutput(writer, reader, "DocumentType");

                break;

            caseXmlNodeType.Comment:

                FormatOutput(writer, reader, "Comment");

                break;

            caseXmlNodeType.Element:

                FormatOutput(writer, reader, "Element");

                break;

            caseXmlNodeType.Text:

                FormatOutput(writer, reader, "Text");

                break;

            caseXmlNodeType.Whitespace:

                break;

        }

    }

    以下是FormatOutput 函数:

    private static void FormatOutput(StreamWriter writer, XmlReader reader, String nodeType)

    {

        //tab使输出的层次分明一点

        for (int i = 0; i < reader.Depth; i++)

        {

            writer.Write('t');

        }

        //这里并没有做过多的判断,但是作为Element的节点并没有Value

        if (reader.Name != String.Empty)

            writer.WriteLine(reader.Prefix + nodeType + "<" + reader.Name + ">:" + reader.Value);

        else

            writer.WriteLine(reader.Prefix + nodeType + ": " + reader.Value);

        // 显示当前节点的属性名和值,同样用tab做了格式控制     

        while (reader.MoveToNextAttribute())

       {

            for (int i = 0; i < reader.Depth; i++)

            writer.Write('"t');

            writer.WriteLine("Attribute: " + reader.Name + "= " + reader.Value);

        }

    }

    输出效果
    XmlDeclaration<xml>:version='1.0'
    Attribute: version= 1.
    Comment: Some of Wrox books in the book database
    Element<bookstore>:
             Element<book>:
                       Attribute: Section= XML
                       Attribute: PublicationDate= 2004
                       Attribute: ISBN= 0-7645-7077-3
                       Element<title>:
                                Text: Beginning XML, 3rd Edition
                       Element<author>:
                                Element<first-name>:
                                         Text: David
                                Element<last-name>:
                                         Text: Hunter
                       Element<price>:
                                Text: 39.99
             Element<book>:
                       Attribute: Section= Java
                       Attribute: PublicationDate= 2004
                       Attribute: ISBN= 0-7645-6874-4
                       Element<title>:
                                Text: Ivor Horton's Beginning Java 2, JDK 5 Edition
                       Element<author>:
                                Element<first-name>:
                                         Text: Ivor
                                Element<last-name>:
                                         Text: Horton
                       Element<price>:
                                Text: 49.99
             Element<book>:
                       Attribute: Section= Database
                       Attribute: PublicationDate= 2005
                       Attribute: ISBN= 0-7645-7950-9
                       Element<title>:
                                Text: Beginning MySQL
                       Element<author>:
                                Element<first-name>:
                                         Text: Robert
                                Element<last-name>:
                                         Text: Sheldon
                       Element<author>:
                                Element<first-name>:
                                         Text: Geoff
                                Element<last-name>:
                                         Text: Moes
                       Element<price>:
                                Text: 39.99

    2) 使用DataSet

    跟在PC 机上一样,在面临复杂数据交互,需要充分利用数据间的相互关系的时候,单向运行的XmlReader 就有些不够用了,因为它不保存流过去的信息,做过ADO.NET 的人对DataSet 应该不会陌生,跟XmlReader 不同,DataSet 就是一个常驻内存的关系型数据库。DataSet 里面的数据即可以来自关系型数据库又可以来自XML 文件( ) 。下面的意思演示了如何从DataSet 加载XML 并在DataGrid 上面显示出来:

    1         DataTable dt1 = null;

     2         DataTable dt2 = null;

     3         DataSet ds = null;

     4         int CurrentTable ;

     5         public Form2()

     6         {

     7             InitializeComponent();

     8         }

     9

     10         private void LoadData()

     11         {

     12             int loadTimeSpan;

     13            

     14             XmlDocument doc = new XmlDocument();

     15             try

     16             {

     17                int t1= System.Environment.TickCount;

     18                 //XML文件读入内存

     19                 doc.Load(@"\Storage Card\books.xml");

     20                 int t2 = System.Environment.TickCount;

     21                 loadTimeSpan = t2 - t1;

     22                 MessageBox.Show("LoadDocTimeSpan:"+loadTimeSpan);

     23             }

     24             catch (XmlException ex)

     25             {

     26                 MessageBox.Show(ex.Message);

     27                 return;

     28             }

     29             Cursor.Current = Cursors.WaitCursor;

     30             //通过XmlNodeReaderXmlDocument中的数据填充到dataSet中去

     31             XmlNodeReader reader = new XmlNodeReader(doc);

     32             int DataSetFillSpan;

     33              ds = new DataSet();

     34                     int t3 = System.Environment.TickCount;

     35             ds.ReadXml(reader);

     36             int t4 = System.Environment.TickCount;

     37             DataSetFillSpan = t4 - t3;

     38             reader.Close();

     39

     40             //因为XML文件里面存在BookAuthor的一对多的主从表

     41             dt1 = ds.Tables[0];

     42             dt2 = ds.Tables[1];

     43             //设置默认显示的表

     44             DG_Book.DataSource = ds.Tables[0].DefaultView;

     45             CurrentTable = 0;

     46             Cursor.Current = Cursors.Default;

     47             MessageBox.Show("Fill dataset timeSpan:"+DataSetFillSpan);

     48         }

     49

     50         private void Form2_Load(object sender, EventArgs e)

     51         {

     52             LoadData();

     53         }

     54

     55          /// <summary>

     56         /// 显示特定行的信息

     57         /// </summary>

     58         /// <param name="bookIndex">行号</param>

     59         private void DisplayDataRow(int bookIndex)

     60         {

     61             String line = String.Empty;

     62             DataTable dt = CurrentTable == 0 ? dt1 : dt2;

     63

     64             DataRow dr = dt.Rows[bookIndex];

     65            

     66             int col = 0;

     67             foreach (object value in dr.ItemArray)

     68             {

     69                 line += (dt.Columns[col].ColumnName + ": " +

     70                     value.ToString() + "\r\n");

     71                 col++;

     72             }

     73             MessageBox.Show(line);

     74         }

     75

     76         private void menuItem3_Click(object sender, EventArgs e)

     77         {

     78             int bookIndex = DG_Book.CurrentRowIndex;

     79             DisplayDataRow(bookIndex);

     80         }

     81

     82         private void menuItem4_Click(object sender, EventArgs e)

     83         {

     84             SwitchTable();

     85         }

     86

     87         private void menuItem5_Click(object sender, EventArgs e)

     88         {

     89             SwitchTable();

     90         }

     91

     92          /// <summary>

     93         /// 在两个表之间切换显示

     94         /// </summary>

     95         private void SwitchTable()

     96         {

     97             if (CurrentTable == 0)

     98              {

     99                 DG_Book.DataSource = dt2.DefaultView;

    100                 CurrentTable = 1;

    101                 this.Text = "Author Table:";

    102             }

    103             else

    104              {

    105                 DG_Book.DataSource = dt1.DefaultView;

    106                 CurrentTable = 0;

    107                 this.Text = "Book Table:";

    108             }

    109         }

    110

    111         private void menuItem1_Click(object sender, EventArgs e)

    112         {

    113             //关闭的时候输出带SchemaXML文件

    114             if (ds != null)

    115              {

    116                 ds.WriteXml(@"\Storage Card\bookstore.xml", XmlWriteMode.WriteSchema);            

    117                 //ds.WriteXmlSchema(@"\Storage Card\bookstore.xsd");

    118             }

    119             Application.Exit();

    120         }

    最后有一点是要强调的是,在使用DataSet 的时候,一定要考虑的数据量的大小,可能超过2K 以上的数据加载的时候速度就有点不能忍受了。我在模拟器上测试用的不到1k 的数据生成XmlDocument 用了1.5 秒,填充DataSet 用了8 秒多,当然在设备上还是要比这快一些。

     

  • 相关阅读:
    Eclipse中配置Tomcat碰到Server Tomcat v6.0 Server at localhost failed to start问题
    解决java中对URL编码的问题
    上白泽慧音
    小K的农场
    [USACO15JAN]草鉴定Grass Cownoisseur
    [HNOI2012]矿场搭建/Mining Your Own Business
    [POI2008]BLO-Blockade
    「JOISC 2018 Day 1」帐篷
    Sudoku
    序列
  • 原文地址:https://www.cnblogs.com/quietwalk/p/1857816.html
Copyright © 2020-2023  润新知