• 文档对象模型操作xml文档


    简介 :文档对象模型(DOM)是一种用于处理xml文档的API函数集。

    2.1文档对象模型概述

    按照W3C的定义,DOM是“一种允许程序或脚本动态地访问更新文档内容,结构和样式的、独立于平台和语言的规范化接口。DOM是表示文档(比如HTML和XML)和访问、操作构成文档的各种元素的应用程序接口,它以树状结构表示HTML和XML文档,定义了遍历这个树和检查、修改树的节点的方法和属性。

    DOM的核心API还允许你创建和填充文件、加载文档并保存。

    2.2DOM实现

    微软的net框架在Systemx.xml命名空间提供了一系列的类用于DOM实现,xmlDocument是NET中Dom实现的核心类之一。正如其他的DOM解析器一样,该类是NET框架的DOC解析器。

    xmlDocument将XML文档视为树状结构,他装在xml文档并在内存中构建该文档的树状结构。XmlDocument类代表了一个xml文档、,它支持xml的增删改查;

    xmlNode代表一个节点。

     
    xml文档组成 部分 对应的类
    Document Element(文档元素) XmlElement
    Processing Instructions(处理指令) XmlProcessingIntruction
    Element(元素)  XmlElement
    Attribute(属性) XmlAttribute
    Text Values(文本值) XmlText
    Nodes(节点) XmlNode

    表中所提及的类都直接或者间接的继承了抽象类的XmlNode。

    2.3应用实例

    2.3.1装载xml文档

    XmlDocument类允许你通过三种方式打开一个xml文档:

    1. 指定xml文档路径路程或者URL 
    2. 包含xml文档数据的文件流对象
    3. 包含xml文档数据的字符串

    接来用这三种方法尝试打开xml文档。代码如下:

     public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnopen_Click(object sender, EventArgs e)
            {
                try 
                {
                    XmlDocument doc = new XmlDocument();
                    if (rdbURL.Checked)
                    {
                        doc.Load(txtpath.Text);
                    }
                    if (rdbstream.Checked)
                    {
                        FileStream stream = new FileStream(txtpath.Text,FileMode.Open);
                        doc.Load(stream);
                        stream.Close();
                    }
                    if (rdbstring.Checked)
                    {
                        doc.LoadXml(txtpath.Text);//加载报错,Loading从指定的字符串中加载xml文档。
                        doc.LoadXml("<customer ><firstname>Ernestine</firstname><lastname>Borrison</lastname><homephone>(445) 269-7742</homephone><notes>123</notes></customer>");
                        //
                    }
    
                    MessageBox.Show("XML Document Opened Successfully!");
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    View Code

     xmlDocument类具有俩个重要的方法:Load()和LoadXml()用于加载文档。Load方法通过指定xml文档的文件路径、URL或指向XML文档的流对象来打开XML 文档。

    LoadXml方法中则通过指定包含xml文档的字符串来打开xml文档。在这个例子中,LoadXml加载的是文件的路径,导致加载无法成功,讲字符串替换为含有根节点的字符串即可,这个字符串中的节点并不一定是xml文档的根节点,是你选取的这个字符串中的根节点,其他节点应该包含在这个节点的内部,不能含有多个同等级的节点。

    2.3.2遍历xml文档

    一个xml文档可以包含一个或者对个节点,而每一个节点又可以包含多个子节点,xmlnode类具有一个叫Childnoes的集合体,该集合体包好某种条件下的所有子节点。net框架中与DOM 相关联的其他许多类都直接或者间接的继承自XmlNode类。因而这些类可以调用childNodes集合体。

    例子代码:

    private void btnload_Click(object sender, EventArgs e)
            {
                XmlDocument _doc = new XmlDocument();//创建实例
                _doc.Load(Application.StartupPath + "/Customers.xml");//加载文件
    
                TreeNode _root = new TreeNode(_doc.DocumentElement.Name);//documentElement 属性可返回文档的根节点
                treeView1.Nodes.Add(_root);
    
                foreach (XmlNode node in _doc.DocumentElement.ChildNodes)
                {
                    TreeNode _customer = new TreeNode("Customer ID : " + node.Attributes["customerid"].Value);//Attributes表示获取对应的属性信息
    
                    _root.Nodes.Add(_customer);
                    if (node.HasChildNodes)
                    {
                        foreach (XmlNode childnode in node.ChildNodes)
                        {
                            TreeNode _customer2 = new TreeNode(childnode.Name + " : " + childnode.InnerText);//InnerText获取节点的内部数据 。。。
                            _customer.Nodes.Add(_customer2);
                        }
                    }
                }
            }
    View Code

    2.3.3查询特殊元素和节点

    在实际的使用中我们使用下面这几种方法来查询xml文档树中的 某个或某些元素和节点,去获得相关的信息和数据值。

    1. Ge他ElementByTagName()方法
    2. GetElementById()方法
    3. SelectNodes()方法
    4. SelectSingleNode()方法

        1、XmlDcument类的GetElementByTagName()方法以节点的标签名为输入参数。并返回所有具有相同标签名的节点。这些节点包含在一个XmlNodeList类的实例中。

    XmlNodeList类代表一个XmlNode对象的集合。代码如下:

     public partial class Form1 : Form
        {
            #region Constructor
            public Form1()
            {
                InitializeComponent();
            }
            #endregion
    
            #region Variables
    
            private XmlNodeList list = null;//代表一个XmlNode对象的集合、
            #endregion
            private void btnsearch_Click(object sender, EventArgs e)
            {
                lstresult.Items.Clear();
    
                XmlDocument _doc = new XmlDocument();
                _doc.Load(Application.StartupPath + "/customers.xml");
    
                list = _doc.GetElementsByTagName(txttag.Text);//通过标签名获取list
    
                foreach (XmlNode node in list)
                {
                    lstresult.Items.Add(node.Name);
                }
            }
    
            private void lstresult_SelectedIndexChanged(object sender, EventArgs e)
            {
                txtresult.Text = list[lstresult.SelectedIndex].InnerText;
            }
    View Code

        2、应用GetElementByld方法

        如果xml文档中存在一个具有唯一值的属性,比如人民的身份证这个属性。在查找特殊元素或者节点时,可应用GetElementByld()方法加以实现,其实现方式类似于应用主键在数据库中

    查询相应的记录。问题在XmlDocument类不能自动的指定元素的某个特殊的属性作为元素的主键,因此在应用这个方法前,必须在xml文档中通过DTD或者Schema技术指定元素的某个属性作为元素的唯一的“主键”,同时使XmlDocument类能够将该属性视为元素的“主键”。

      声明主键的代码如下:

    <!DOCTYPE customers[
      <!ELEMENT customers ANY>
      <!ELEMENT customer ANY>
      <!ELEMENT firstname ANY>
      <!ELEMENT lastname ANY>
      <!ELEMENT homephone ANY>
      <!ELEMENT notes ANY>
      <!ATTLIST customer customerid ID #REQUIRED>
    ]>
    View Code

      注意这行代码<!ATTLIST customer customerid ID #REQUIRED>,在此我们将属性customer id 标记为ID并同时规定其实唯一的(#REQUIRED) 

      这个方法的返回值是包含相应节点数据的XmlElement类的实例对象。

     private void Form1_Load(object sender, EventArgs e)
            {
                doc = new XmlDocument();
                doc.Load(Application.StartupPath+"/Customers.xml");
                foreach(XmlNode node in doc.DocumentElement.ChildNodes)
                {
                    string _strid=node.Attributes["customerid"].Value;
                    cmbID.Items.Add(_strid);
                }
            }
    
            private void cmbID_SelectedIndexChanged(object sender, EventArgs e)
            {
                XmlElement _xel = doc.GetElementById(cmbID.SelectedItem.ToString());
                lblfirst.Text = _xel.ChildNodes[0].InnerText;
                lbllast.Text = _xel.ChildNodes[1].InnerText;
                lblphone.Text = _xel.ChildNodes[2].InnerText;
                lblnote.Text = _xel.ChildNodes[3].InnerText;
            }
    View Code

      3、应用SelectNodes()方法

      在某些情况下,我们需要查询xml文档中付某中或者某些条件的节点。SelectNodes()可以满足这种要求,该方法可以根据查询条件过滤得到符合条件的节点。

      返回值一个包含所有有效节点得到XmlNodeList实例对象。

    public partial class Form1 : Form
        {
            #region ariables
    
            private XmlNodeList list = null;
            #endregion
    
            #region Constructor
    
            public Form1()
            {
                InitializeComponent();
            }
            #endregion
            private void btnsearch_Click(object sender, EventArgs e)
            {
                lstresult.Items.Clear();
                XmlDocument _doc = new XmlDocument();
                _doc.Load(Application.StartupPath + "/Customers.xml");
                if (rdbfirst.Checked)
                {
                    //string str = string.Format("//customer[./firstname/text()='{0}']", txtinput.Text);
                    //
                    string str = string.Format("//customer[./homephone[./quhao/text()='{0}']]", txtinput.Text);
                    //////customer[./firstname/text()='John']
                    list = _doc.SelectNodes(str);
                }
                if (rdblast.Checked)
                {
                    list = _doc.SelectNodes(string.Format("//customer[./lastname/text()='{0}']", txtinput.Text));
                }
                foreach (XmlNode node in list)
                {
                    lstresult.Items.Add(node.Attributes["customerid"].Value);
                }
    
            }
    
            private void btndetail_Click(object sender, EventArgs e)
            {
                if (lstresult.SelectedIndex < 0)
                {
                    MessageBox.Show("Please Selected a Customer ID");
                }
                else
                {
                    lblfirst.Text = list[lstresult.SelectedIndex].ChildNodes[0].InnerText;
                    lbllast.Text = list[lstresult.SelectedIndex].ChildNodes[1].InnerText;
                    lblphone.Text = list[lstresult.SelectedIndex].ChildNodes[2].InnerText;
                    lblnote.Text = list[lstresult.SelectedIndex].ChildNodes[3].InnerText;
                }
            }
    View Code

    4、应用selectSingleNode()方法

       该刚方法的不同于selectNodes的是:方法仅返回符合条件的第一个节点。

    2.4修改XML文档

      对XML文档的修改包括添加或者插入新节点,删除已存在节点、次该节点的相关数据或者属性。DOM 是一个读写型的解释器,因此dom也有提供许多函数方法和类允许你修改文档。

    2.4.1 Save方法

      save方法保存文件到指定的位置。 该方法传入的参数为XmlWriter、XmlTextWriter或者字符串。

                string filename=@“C:ooks.xml”;
                XmlDocument xmlDoc= new XmlDocument();
                xmlDoc.Load(filename);
                XmlTextWriter writer = new XmlTextWriter("c:\domtest.xml",null);
                writer.Formatting=Formatting.Indented;
                xmlDoc.Save(writer);
                //你也可以使用一个文件名或Console.Out保存文档,或者将文档的内容输出到屏幕上
                xmlDoc.Save("c:\domtest.xml");
                xmlDoc.Save(Console.Out);
    View Code

    2.4.2 XmlDocumentFragment类

      在xml 文档中插入部分内容或者节点时,用到这个类=》这个类自XmlNode派生。=>通过xml文档的CreateDocumentFragment()方法来创建这个类的实例。

    该实例的InnerXml属性代表当前节点的子节点。

     XmlDocumentFragment docFrag=xmlDoc.CreateDocumentFragment();

    2.4.3 XmlElement类

      XmlElement代表文档中的一个元素,这个类继承自XmlLinkedNode,XmlLinkedNode类继承自XmlNode。XmlLinkedNode有俩个属性:NextSibing和PreviousSibling、代表与当前节点处于同一个层次的下一个和以前的节点。

      下面网址链接此类的常用方法:网址链接

    2.4.4 添加节点到XML 文档中

      AppendChild()方法添加节点到文档中,方法接受一个XmlNode类类型的单个参数。xmldocument的creatxxx方法可以创建不同的节点,AppendChild可以将他们加到文档中。

    添加评论节点代码:xmlDoc.AppendChild(nodel);

    添加元素节点到文档中:xmlDoc.DocumentElement.AppendChild(nodel);

    2.4.5 删除和更换节点

    XmlNode类的RemoveAll()方法可以删除所有元素和节点的属性、方法RemoveChild()仅用于删除指定的子节点。

    代码:XmlNode root= xmlDoc.DocumentElement;root.RemoveALll();

    ReplaceChild()方法用于一个新的节点替换旧的节点rootNode.ReplaceChild(xmlDocFragment,rootNode.LastChild);

    2.4.6 XML片段插入到xml文档中

    XmlNode类提供相应的方法将xml片段插入到xml文档中,例如:InsertAfter()方法在当前节点之后插入一个文档或者元素。

    该方法需要俩个参数,1:XmlDocumentFragment对象,2:要在其中插入片段的位置。(插入位置)

    aNode.InsertAfter(xmlDocFragment,aNode.LastChild);

    2.4.7添加属性到节点中

      使用XmlElement类的SetAttributeNode()方法添加节点的属性。

       XmlElement newElem=xmlDoc.CreateElement("NewElement");
    //创建指定名称的元素
      XmlAttribute newAttr=xmlDoc.CreateAttribute("NewAttribute");
      newElem.SetAttributeNode(newAttr);

    2.5综合实例

     public partial class Form1 : Form
        {
            #region Variables
    
            private XmlDocument doc;
            private int nodeindex = 0;
    
            private bool isadd = false;
            #endregion
    
            #region Constructor
    
            public Form1()
            {
                InitializeComponent();
    
            }
            #endregion
    
            #region Methods
    
            private void AddItemsIntoCombBox(XmlDocument _doc)
            {
                cmbID.Items.Clear();
                foreach (XmlNode _node in _doc.DocumentElement.ChildNodes)
                {
                    cmbID.Items.Add(_node.Attributes["customerid"].Value);
                }
            }
            private void NodeRemoved(object sender, XmlNodeChangedEventArgs e)
            {
                MessageBox.Show("Node " + e.Node.Name + " removed successfully!");
            }
    
            private void NodeInserted(object sender, XmlNodeChangedEventArgs e)
            {
                if (isadd)
                {
                    MessageBox.Show("Node " + e.Node.Name + " added successfully!");
                }
                isadd = false;
            }
    
            private void NodeChanged(object sender, XmlNodeChangedEventArgs e)
            {
                MessageBox.Show("Node " + e.Node.Name + " changed successfully!");
            }
            private void FillControlters()
            {
                XmlNode _nod = doc.DocumentElement.ChildNodes[nodeindex];
                cmbID.Text = _nod.Attributes["customerid"].Value;
                txtfname.Text = _nod.ChildNodes[0].InnerText;
                txtlname.Text = _nod.ChildNodes[1].InnerText;
                txtphone.Text = _nod.ChildNodes[2].InnerText;
                txtnote.Text = _nod.ChildNodes[3].InnerText;
    
                this.UpdateInformation();
            }
            private void UpdateInformation()
            {
                lblinformation.Text = "Customer " + (nodeindex + 1) + " of " + doc.DocumentElement.ChildNodes.Count.ToString();
            }
            #endregion
    
            private void Form1_Load(object sender, EventArgs e)
            {
                doc = new XmlDocument();
                doc.Load(Application.StartupPath + "/customers.xml");
    
                this.AddItemsIntoCombBox(doc);
    
                this.FillControlters();
    
                doc.NodeChanged += new XmlNodeChangedEventHandler(NodeChanged);
                doc.NodeInserted += new XmlNodeChangedEventHandler(NodeInserted);
                doc.NodeRemoved += new XmlNodeChangedEventHandler(NodeRemoved);
    
            }
    
            private void btnadd_Click(object sender, EventArgs e)
            {
                if ((txtfname.Text == "") || (txtlname.Text == "") || (txtphone.Text == "") || (txtnote.Text == ""))
                {
                    MessageBox.Show("Please fill up all items of customer!");
                    return;
                }
                XmlElement _customer = doc.CreateElement("customer");
                XmlElement _firstname = doc.CreateElement("firstname");
                XmlElement _lastname = doc.CreateElement("lastname");
                XmlElement _homephone = doc.CreateElement("homephone");
                XmlElement _notes = doc.CreateElement("notes");
    
                XmlAttribute _customerid = doc.CreateAttribute("customerid");
                _customerid.Value = cmbID.Text;
    
                XmlText _firstnametext = doc.CreateTextNode(txtfname.Text);
                XmlText _lastnametext = doc.CreateTextNode(txtlname.Text);
                XmlText _homephonetext = doc.CreateTextNode(txtphone.Text);
                XmlCDataSection _notestext = doc.CreateCDataSection(txtnote.Text);
    
                _customer.Attributes.Append(_customerid);
                _customer.AppendChild(_firstname);
                _customer.AppendChild(_lastname);
                _customer.AppendChild(_homephone);
                _customer.AppendChild(_notes);
    
                _firstname.AppendChild(_firstnametext);
                _lastname.AppendChild(_lastnametext);
                _homephone.AppendChild(_homephonetext);
                _notes.AppendChild(_notestext);
    
                isadd = true;
    
                doc.DocumentElement.AppendChild(_customer);
                doc.Save(Application.StartupPath + "/Customers.xml");
    
                this.AddItemsIntoCombBox(doc);
    
                this.UpdateInformation();
            }
    
            private void btnupdate_Click(object sender, EventArgs e)
            {
                if ((txtfname.Text == "") || (txtlname.Text == "") || (txtphone.Text == "") || (txtnote.Text == ""))
                {
                    MessageBox.Show("Please fill up all items of customer!");
                    return;
                }
                XmlNode _node = doc.SelectSingleNode("//customer[@customerid='" + cmbID.SelectedItem + "']");
                if (_node != null)
                {
                    if (_node.ChildNodes[0].InnerText != txtfname.Text)
                        _node.ChildNodes[0].InnerText = txtfname.Text;
                    if (_node.ChildNodes[1].InnerText != txtlname.Text)
                        _node.ChildNodes[1].InnerText = txtlname.Text;
                    if (_node.ChildNodes[2].InnerText != txtphone.Text)
                        _node.ChildNodes[2].InnerText = txtphone.Text;
                    if (_node.ChildNodes[3].InnerText != txtnote.Text)
                    {
                        XmlCDataSection _notes = doc.CreateCDataSection(txtnote.Text);
                        isadd = true;
                        _node.ChildNodes[3].ReplaceChild(_notes, _node.ChildNodes[3].ChildNodes[0]);
                    }
                }
                doc.Save(Application.StartupPath + "/Customers.xml");
            }
    
            private void btndelete_Click(object sender, EventArgs e)
            {
                XmlNode _node = doc.SelectSingleNode("//customer[@customerid='" + cmbID.SelectedItem + "']");
                if (_node != null)
                {
                    doc.DocumentElement.RemoveChild(_node);
                }
                doc.Save(Application.StartupPath + "/Customers.xml");
    
                nodeindex = 0;
                this.FillControlters();
                this.UpdateInformation();
                this.AddItemsIntoCombBox(doc);
            }
    
            private void btnfirst_Click(object sender, EventArgs e)
            {
                nodeindex = 0;
                this.FillControlters();
            }
    
            private void btnprevious_Click(object sender, EventArgs e)
            {
                nodeindex--;
                if (nodeindex < 0)
                {
                    nodeindex = 0;
                }
                this.FillControlters();
            }
    
            private void btnnext_Click(object sender, EventArgs e)
            {
                nodeindex++;
                if (nodeindex >= doc.DocumentElement.ChildNodes.Count)
                {
                    nodeindex = doc.DocumentElement.ChildNodes.Count - 1;
                }
                this.FillControlters();
            }
    
            private void btnlast_Click(object sender, EventArgs e)
            {
                nodeindex = doc.DocumentElement.ChildNodes.Count - 1;
                this.FillControlters();
            }
    View Code

    2.6处理空白

      加载文档时,默认情况下,XMLDocument类忽略空白。通过设置PreserveWhiteSpace的布尔型属性来控制是否需要空白内容,true将保存空白内容,false将不保留空白内容。

    2.7XmlDocument类的事件

       当修改xml 文档时,会激发小毛驴document类提供的事件过程,这些事件过程分别遵循事前或者事后激发模式。

    System_CAPS_pubevent NodeChanged

    当属于该文档的节点的 Value 已被更改时发生。

    System_CAPS_pubevent NodeChanging

    当属于该文档的节点的 Value 将被更改时发生。

    System_CAPS_pubevent NodeInserted

    当属于该文档的节点已被插入另一个节点时发生。

    System_CAPS_pubevent NodeInserting

    当属于该文档的节点将被插入另一个节点时发生。

    System_CAPS_pubevent NodeRemoved

    Occurs when a node belonging to this document has been removed from its parent.

    System_CAPS_pubevent NodeRemoving

    当属于该文档的节点将从文档中移除时发生。

     

    表中的事件都接受一个XmlNodeChangeEventArgs类型的参数

    下面提供这个类型参数的一些属性

    System_CAPS_pubproperty Action

    获取一个值,该值指示正在发生哪种类型的节点更改事件。

    System_CAPS_pubproperty NewParent

    获取操作完成后 ParentNode 的值。

    System_CAPS_pubproperty NewValue

    获取节点的新值。

    System_CAPS_pubproperty Node

    获取正被添加、移除或更改的 XmlNode

    System_CAPS_pubproperty OldParent

    获取操作开始前的 ParentNode 的值。

    System_CAPS_pubproperty OldValue

    获取节点的原始值。

  • 相关阅读:
    运算符重载
    vmware 下 ubuntu 不能全屏显示 的解决方法
    最优化
    常见算法(logistic回归,随机森林,GBDT和xgboost)
    转:CRF++词性标注
    条件随机场(CRF)理论及应用
    转:RNN(Recurrent Neural Networks)
    RNN(Recurrent Neural Networks)公式推导和实现
    ML、DL相关资源
    机器学习(周志华西瓜书) 参考答案 总目录
  • 原文地址:https://www.cnblogs.com/zhlziliaoku/p/5221054.html
Copyright © 2020-2023  润新知