| 搜索频道 | 源码下载 | 站长代码论坛 | 文章分类 | 最新专题 | 源码交易 | 加入收藏
首页|资讯|图形图像|网站开发|程序设计|数据库|多媒体|机械电子|办公系列|路由技术|原理|应用|考试|系统
文章搜索:
 您的位置:首页网站开发XML → 修改大型 XML 文件的有效方法
修改大型 XML 文件的有效方法

日期:2006-7-12 11:46:54 人气:     [ ]
引言
随着 XML 成为大型信息源的常用表示格式,开发人员编辑大型 XML 文件时开始遇到问题。对于处理大型日志文件以及经常需要为这些文件追加信息的应用程序,尤其如此。编辑 XML 文件最直接的方法是,将其加载到 XmlDocument 中,在内存中修改文档,然后将其保存回磁盘。但是,这样做意味着要将整个 XML 文档加载到内存中,由于文档太大或应用程序需要的内存不够,这种方法可能会行不通。

这篇论文说明了修改 XML 文档的一些可供选择的方法,这些方法不涉及将文档加载到 XmlDocument 实例中的内容。

使用 XML 包含方法
建议的第一种方法对于向 XML 日志文件追加值最为有用。开发人员面临的常见问题是需要一种能够将新条目简单地追加到日志文件中而不用加载文档的方法。因为 XML 具有良好结构规则,所以使用传统方式(这种方法会因为日志文件格式不正确而结束日志文件)来向 XML 日志文件追加条目通常是非常困难的。

要说明的第一种方法是针对这样的情形,即目的是能够将条目快速地追加到 XML 文档中。这种方法包括创建两个文件。第一个文件是格式正确的 XML 文件,第二个是 XML 片段。格式正确的 XML 文件包括 XML 片段,XML 片段使用 DTD 中声明的 external entity 或者使用 xi:include element 。使用包含文件,通过在进行处理过程中简单地追加到 XML 文件,可以有效地更新文件包含 XML 片段的方法。包含文件和被包含文件的示例如下所示:

Logfile.xml:
<?xml version="1.0"?>
<!DOCTYPE logfile [
<!ENT99vY events
SYSTEM "logfile-entries.txt">
]>
<logfile>
&events;
</logfile>

Logfile-events.txt:
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>index.html</file>
<date>2004-04-01T17:35:20.0656808-08:00</date>
</event>
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>stylesheet.css</file>
<date>2004-04-01T17:35:23.0656120-08:00</date>
<referrer>http://www.example.com/index.html</referrer>
</event>
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>logo.gif</file>
<date>2004-04-01T17:35:25.238220-08:00</date>
<referrer>http://www.example.com/index.html</referrer>
</event>

logfile-entries.txt 文件包括一个 XML 片段,并且可以使用典型的文件 IO 方法有效地进行更新。下面的代码说明了如何通过将条目追加到文本文件的结尾来将它添加到 XML 日志文件中。

using System;
using System.IO;
using System.Xml;

public class Test{
public static void Main(string[] args){

StreamWriter sw = File.AppendText("logfile-entries.txt");
XmlTextWriter xtw = new XmlTextWriter(sw);

xtw.WriteStartElement("event");
xtw.WriteElementString("ip", "192.168.0.1");
xtw.WriteElementString("http_method", "POST");
xtw.WriteElementString("file", "comments.aspx");
xtw.WriteElementString("date", "1999-05-05T19:25:13.238220-08:00");

xtw.Close();

}
}

一旦条目被追加到文本文件中,使用传统的 XML 处理方法,就可以处理 XML 日志文件中的条目。下面的代码使用 XPath 遍历了 logfile.xml 中的日志事件,同时列出了它们被访问时的文件以及被访问的文件。

using System;
using System.Xml;

public class Test2{

public static void Main(string[] args){

XmlValidatingReader vr =
new XmlValidatingReader(new XmlTextReader("logfile.xml"));
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;

XmlDocument doc = new XmlDocument();
doc.Load(vr);

foreach(XmlElement element in doc.SelectNodes("//event")){

string file = element.ChildNodes[2].InnerText;
string date = element.ChildNodes[3].InnerText;

Console.WriteLine("{0} accessed at {1}", file, date);

 

}
}
}

上面的代码导致了下面的输出:

index.html accessed at 2004-04-01T17:35:20.0656808-08:00
stylesheet.css accessed at 2004-04-01T17:35:23.0656120-08:00
logo.gif accessed at 2004-04-01T17:35:25.238220-08:00
comments.aspx accessed at 1999-05-05T19:25:13.238220-08:00


更改 XmlReader 为 XmlWriter
在某些情况下,除了只将元素追加到根元素中外,还需要对 XML 文件执行更复杂的操作。例如,要筛选日志文件中的每一个条目,而这些条目在存档到日志文件前不符合某些特殊标准。要完成此任务的一种方法是将 XML 文件加载到 XmlDocument 中,然后通过 XPath 选择感兴趣的事件。但是,这样做涉及将整个文档加载到内存中,如果文档太大,则这种做法会受到限制。另一种选择方法为了这种任务会涉及使用 XSLT,但是由于整个 XML 文档需要保存到内存中,这种方法会和 XmlDocument 方法一样遇到相同的问题。另外,由于开发人员不熟悉 XSLT,了解如何正确使用模板匹配时会遇到较大的困难。

要解决如何处理大型 XML 文档问题的一种方法是使用 XmlReader 读取 XML,读取的同时使用 XmlWriter 将其写出。使用这种方法,整个文档不会同时存入内存中,对 XML 可以进行更精确的更改而不只是追加元素。下面的代码示例读取前面部分的 XML 文档,筛选出所有 ip 元素的值为 "127.0.0.1" 的事件后将其保存为存档文件。

using System;
using System.Xml;
using System.IO;
using System.Text;
public class Test2{
static string ipKey;
static string httpMethodKey;
static string fileKey;
static string dateKey;
static string referrerKey;

public static void WriteAttributes(XmlReader reader, XmlWriter writer){

if(reader.MoveToFirstAttribute()){
do{
writer.WriteAttributeString(reader.Prefix,
reader.LocalName,
reader.NamespaceURI,
reader.Value);
}while(reader.MoveToNextAttribute());
reader.MoveToElement();
}
}

public static void WriteEvent(XmlWriter writer, string ip,
string httpMethod, string file,
string date, string referrer){

writer.WriteStartElement("event");
writer.WriteElementString("ip", ip);
writer.WriteElementString("http_method", httpMethod);
writer.WriteElementString("file", file);
writer.WriteElementString("date", date);
if(referrer != null) writer.WriteElementString("referrer", referrer);
writer.WriteEndElement();

}

public static void ReadEvent(XmlReader reader, out string ip,
out string httpMethod, out string file,
out string date, out string referrer){

ip = httpMethod = file = date = referrer = null;

while( reader.Read() && reader.NodeType != XmlNodeType.EndElement){

if (reader.NodeType == XmlNodeType.Element) {

if(reader.Name == ipKey){
ip = reader.ReadString();
}else if(reader.Name == httpMethodKey){
httpMethod = reader.ReadString();
}else if(reader.Name == fileKey){
file = reader.ReadString();
}else if(reader.Name == dateKey){
date = reader.ReadString();
// reader.Read(); // 使用结尾标记
}else if(reader.Name == referrerKey){
referrer = reader.ReadString();
}
}//if
}//while
}

public static void Main(string[] args){
string ip, httpMethod, file, date, referrer;
//使用用于进行比较的字符串设置 XmlNameTable
XmlNameTable xnt = new NameTable();
ipKey = xnt.Add("ip");
httpMethodKey = xnt.Add("http_method");
fileKey = xnt.Add("file");
dateKey = xnt.Add("date");
referrerKey = xnt.Add("referrer");

//使用上面的 XmlNameTable 加载 XmlTextReader
XmlTextReader xr = new XmlTextReader("logfile.xml", xnt);
xr.WhitespaceHandling = WhitespaceHandling.Significant;

 

XmlValidatingReader vr = new XmlValidatingReader(xr);
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;

StreamWriter sw =
new StreamWriter ("logfile-archive.xml", false, Encoding.UTF8 );
XmlWriter xw = new XmlTextWriter (sw);

vr.MoveToContent(); // 移到文档元素
xw.WriteStartElement(vr.Prefix, vr.LocalName, vr.NamespaceURI);
WriteAttributes(vr, xw);

vr.Read(); // 移到文档元素的第一个 <event> 子元素
// 写出不是 127.0.0.1(本地主机)中的事件
do
{
ReadEvent(vr, out ip, out httpMethod,
out file, out date, out referrer);
if(!ip.Equals("127.0.0.1")){
WriteEvent(xw,ip, httpMethod, file, date, referrer);
}
vr.Read(); //移到下一个 <event> 元素或 <logfile> 的结尾标记
} while(vr.NodeType == XmlNodeType.Element);

Console.WriteLine("Done");

vr.Close();
xw.Close();
}
}

上面的代码示例在写入到 logfile-archive.xml 文件中时会导致下面的输出:

<logfile>
<event>
<ip>192.168.0.1</ip>
<http_method>POST</http_method>
<file>comments.aspx</file>
<date>1999-05-05T19:25:13.238220-08:00</date>
</event>
</logfile>

除了使用 XmlReader 到 XmlWriter 的链之外,上面代码的另一个有趣方面是,使用 ReadEvent() 方法检查元素标记名称时使用 NameTable 提高了文本比较的性能。在 XmlReader 中使用这种方法检查元素的标记名称的优点在如下的 MSDN 文档主题中进行了概述:Object Comparison Using XmlNameTable with XmlReader(英文)。

出处:本站原创 作者:zzcode
 相关文章
·使用xmlhttp 实现多文件上传
·利用oleDB对象,将数据库中全部表转换成XML文件
·XML 使用NodeList对象
·简析JAVA的XML编程
·XML使用其它方法来存取元素
·把HTML表单提交的数据转化成XML文件
·存取XML的属性
·XML与其相关技术
·浏览整个XML文件
·XML入门精解之结构与语法
 相关软件
·ASP+XML 精美留言本
·E路XML留言本(Elook XML GuestBook) v1.0 无组件..
·爱上网XML自助链接
·JOB571.COM即插即用自助友情链接(XML版)
·XML 编程从入门到精通(PDF)
·厦门普工招聘网XML留言簿
·XMLBlueprint XML Editor v3.6
·Altova XMLSpy 2005 SP3 企业特别版
·Ektron eWebEditPro+XML v4.2.0.11 特别版
·XMLwriter v2.5 特别版
 

 热点文章

·用ASP、VB和XML建立互..
·XML新增批注、处理指令..
·XML 中的常见问题
·简单的XML留言板
·带可选项、带图片的无..
·将XML文件链接至HTML网..
·用XML实现国家、省的动..
·XML与其相关技术
·简析JAVA的XML编程
·构造未来Web页面的工具..
·web.xml中的 security..
·使用xmlhttp 实现多文..
·利用XML不离开页面刷新..
·XML入门精解之结构与语..
·SQL Server和XML的集成..

 推荐文章

·端午非物质文化遗产登..
·动态网站Web开发PHP、..
·PS绘中秋佳节的一轮明..
·细谈网页优化和网站优..
·建站常识:如何使用FT..
·如何快速建造一个成功..
·ASP.NET 2.0 中的创建..
·ASP.NET2.0服务器控件..
·在ASP.NET应用中插入f..
·用Photoshop打造逼真立..
·Windows 2003搭建虚拟..
·站长必读:Web创业的1..
·如何测试机房的速度和..
·北京奥运体育图标发布..
·网络视频广告将身价百..