C#高级编程之处理XML-连载九

时间:2010年04月12日 点击:158

23.6  .NET中使用DOM

.NET 中的文档对象模型(Document Object ModelDOM)支持W3C DOM Level 1 Core DOM Level 2规范。DOM是通过XmlNode类来实现的。XmlNode是一个抽象类,它表示XML文档的一个节点。

还有一个XmlNodeList类,它是一个节点的有序列表。这是一个活动的节点列表,对节点的任何修改都会立即反映到列表中。XmlNodeList支持索引访问或迭代访问。另一个抽象类XmlCharacterData扩展了 XmlLinkedNode,为其他类提供文本处理方法。

XmlNodeXmlNodeList类组成了.NET FrameworkDOM的核心,表23-4是基于XmlNode的一些类。

 23-4

   

  

XmlLinkedNode

返回当前节点之前或之后的节点。给XmlNode.添加NextSiblingPreviousSibling属性

XmlDocument

表示整个文档,执行DOM Level 1 Level 2规范

XmlDocumentFragment

表示文档树的一个片段

XmlAttribute

XmlElement对象的一个属性对象

XmlEntity

一个已分析或未分析的实体节点

XmlNotation

包含在DTD或模式中声明的记号

 

23-5中的类扩展了XmlCharacterData

 23-5

    

    

XmlCDataSection

表示文档中CData部分的一个对象

XmlComment

表示一个XML注释对象

XmlSignificantWhitespace

表示带有空白的节点。只有PreserveWhiteSpace标志为true时,才能创建节点

XmlWhitespace

表示元素内容中的空白格,只有PreserveWhiteSpace标志为true时,才能创建节点

XmlText

元素或属性的文本内容。

 

最后,表23-6的类扩展了XmlLinkedNode

 23-6

   

   

XmlDeclaration

表示声明节点 (<?xml version='1.0'…>)

XmlDocumentType

与文档类型声明相关的数据

XmlElement

一个XML元素对象

XmlEntityReferenceNode

表示一个实体引用节点

XmlProcessingInstruction

包含XML处理指令

 

可以看出,.NET使其类适合于任何XML类型。因此,该工具集是非常灵活和强大的。我们不打算详细介绍每个类,而是用几个示例来说明可以完成什么任务。其层次结构如图23-5   所示。

  23-5

使用XmlDocument对象

XmlDocument及其派生类XmlDataDocument(详见本章后面的内容)是用于在.NET中表示DOM的类。与XmlReader XmlWriter不同,XmlDocument具有读写功能,并可以随机访问DOM树。XmlDocument类似于MSXML中的DOM执行方式。如果您用MSXML编过程序,就会觉得使用XmlDocument很合适。

下面介绍的示例创建一个XmlDocument对象,加载磁盘上的一个文档,再从标题元素中加载带有数据的列表框,这类似于XmlReader一节的示例,区别是本例选择要使用的节点,而不是像XmlReader示例那样浏览整个文档。

下面是该示例的代码,与XmlReader示例相比,这个示例是比较简单的(该文件在下载的DOMSample1文件夹中)

private void button1_Click(object sender, System.EventArgs e)

{

   // doc is declared at the module level

   // change path to match your path structure

   doc.Load("..\\..\\..\\books.xml");

   // get only the nodes that we want

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

   // iterate through the XmlNodeList

   foreach(XmlNode node in nodeLst) listBox1.Items.Add(node.InnerText);

}

注意,我们在本节的示例中添加了模块级的声明:

private XmlDocument doc=new XmlDocument();

如果这就是我们需要完成的工作,使用XmlReader加载列表框就是一种非常高效的方式,原因是我们只浏览一次文档,就完成了处理。这就是XmlReader的工作方式。但如果要重新查看某个节点,最好使用XmlDocument。扩展该示例,添加另一个事件处理程序(DOMSample2)

private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)

{

   //create XPath search string

   string srch="bookstore/book[title='" + listBox1.SelectedItem.ToString()

                                        + "']";

   //look for the extra data

   XmlNode foundNode = doc.SelectSingleNode(srch);

   if(foundNode != null)

      MessageBox.Show(foundNode.InnerText);

   else

      MessageBox.Show("Not found");

}

在这个示例中,与上一个示例一样,从books.xml 文档中加载了带有标题的列表框。单击列表框,会引发SelectedIndexChanged()事件,获取列表框中所选项的文本(书名),创建一个XPath 语句,把它传送给doc对象的SelectSingleNode() 方法,该方法返回title是书名的一部分的book元素(foundNode)。在消息框中显示节点的InnerText。继续单击列表框中的项目,此时文档已经加载,且一直到释放它之前,它都处于已加载状态。

 

下面简要介绍一下SelectSingleNode()方法,它是XmlDocument类的Xpath实现,SelectSingleNode () SelectNodes()都是在XmlNode中定义的,而XmlDocument是基于XmlNode的。SelectSingleNode()返回一个XmlNodeSelectNodes()返回一个XmlNodeListSystem.Xml.XPath命名空间包含许多Xpath实现。后面的一节会介绍它们。

1. 插入节点

前面的示例使用XmlTextWriter创建一个新文档。其局限性是不能把节点插入到当前文档中。而使用XmlDocument类可以做到这一点。把上一个示例中的button1_Click()事件处理程序作如下改动(在下载代码的DOMSample3)

private void button1_Click(object sender, System.EventArgs e)

{

   //change path to match your structure

   doc.Load("..\\..\\..\\books.xml");

   //create a new 'book' element

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

   //set some attributes

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

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

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

   //create a new 'title' element

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

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

   newBook.AppendChild(newTitle);

   //create new author element

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

   newBook.AppendChild(newAuthor);

   //create new name element

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

   newName.InnerText="C. Monster";

   newAuthor.AppendChild(newName);

   //create new price element

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

   newPrice.InnerText="9.95";

   newBook.AppendChild(newPrice);

   //add to the current document

   doc.DocumentElement.AppendChild(newBook);

   //write out the doc to disk

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

   tr.Formatting=Formatting.Indented;

   doc.WriteContentTo(tr);

   tr.Close();

   //load listBox1 with all of the titles, including new one

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

   foreach(XmlNode node in nodeLst)

      listBox1.Items.Add(node.InnerText);

}

在执行这段代码后,会得到与上一个示例相同的结果,但本例在列表框中添加了一本书:The Case of the Missing Cookie。单击cookie caper标题,会显示与其他标题一样的信息。中断代码,可以看出,这是一个相当简单的过程。首先,创建一个新的book元素:

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

CreateElement()3个重载方法,可以指定:

       元素名

       名称和命名空间URI

       前缀、本地名和命名空间

创建了该元素后,就要添加属性了:

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

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

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

创建了属性后,就要添加书籍的其他元素了:

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

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

newBook.AppendChild(newTitle);

再次创建一个新的基于XmlElement的对象(newTitle),把InnerText属性设置为新书名,把该元素添加为book元素的一个子元素。对book元素中的其他元素重复这一操作。注意把name元素添加为author元素的一个子元素。这样就可以在其他book元素中得到合适的嵌套关系。

最后把newBook元素添加到doc.DocumentElement节点上,它与其他book元素同级。现在用新元素更新现有的文档。

最后,把新XML文档写到磁盘上。在这个示例中,创建一个新XmlTextWriter,把它传送给WriteContentTo方法。WriteContentTo WriteTo方法都带一个XmlTextWriter参数。WriteContentTo把当前节点及其所有的子节点都保存到XmlTextWriter,而WriteTo只保存当前节点。因为doc是一个基于XmlDocument的对象,它表示整个文档,所以应保存它。我们还使用了Save方法,它总是保存整个文档,Save4个重载方法,其参数分别是一个包含文件名和路径的字符串、基于Stream的对象、基于TextWriter的对象和基于XmlWriter的对象。

我们还在XmlTextWriter上调用了Close()方法,刷新内部缓存,并关闭文件。

在运行这个示例时,会得到如图23-6所示的屏幕图。注意列表框底部的新项。

  23-6

如果要从头开始创建一个文档,可以使用XmlTextWriter(见本章前面的介绍)。还可以使用XmlDocument。使用哪个比较好?如果要写入XML流的数据已经准备好,最好选择XmlTextWriter类。但是,如果需要一次建立XML文档的一小部分,在不同的地方插入节点,用XmlDocument创建文档就比较好。为此,可以把下面的代码:

   doc.Load("..\\..\\..\\books.xml");

改为(这些代码在示例DOMSample4)

   //create the declaration section

   XmlDeclaration newDec = doc.CreateXmlDeclaration("1.0",null,null);

   doc.AppendChild(newDec);

   //create the new root element

   XmlElement newRoot = doc.CreateElement("newBookstore");

   doc.AppendChild(newRoot);

首先创建一个新XmlDeclaration,其参数是版本(目前是"1.0")、编码(edcoding)standalone标志。如果没有使用null,编码参数应设置为一个字符串,该字符串应是System.Text.Encoding类的一部分。null默认为UTF-8standalone标志可以是yesnonull,但如果是null,就不使用该属性,也不包含在文档中。

要创建的下一个元素是DocumentElement。在本例中,它称为newBookstore,这样区别就比较明显。代码的其余部分与前面的示例相同,执行的方式也相同。下面是从代码中生成的booksEdit.xml

<?xml version="1.0"?>

<newBookstore>

   <book genre="Mystery" publicationdate="2001" ISBN="123456789">

      <title>The Case of the Missing Cookie</title>

      <author>

         <name>C. Monster</name>

      </author>

      <price>9.95</price>

   </book>

</newBookstore>

本章没有介绍XmlDocument类的每个细节,也没有介绍在.NET中对创建DOM模型有帮助的其他类。但是,我们说明了.NET中的DOM有多么灵活和强大。在希望随机访问文档时,可以使用XmlDocument类。在希望有一个流类型的模型时,可以使用基于XmlReader的类。基于XmlDocumentXmlNode的灵活性要求的内存比较多,读取文档的性能也没有使用XmlReader好,所以应仔细考虑在这种情况下最好使用什么方法。

www.zdexe.com
www.zdexe.com

赞助商链接

热门内容

相关内容

联系我们

联系方式