首页 电脑学院 黑客教程 网站技术 网页特效 免费论文 公文写作 演讲发言 实用文档 职场指南 时尚生活 情感男女 其他资讯

您的位置:首页-> 网站技术-> .NET技术-> 修改大型 XML 文件的有效方法
修改大型 XML 文件的有效方法
引言
随着 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 [
<!ENTITY 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(英文)。


在百度中查找更多修改大型 XML 文件的有效方法的内容
职场宝典   职场故事   职场跳槽   职场文化   职场理财   职场充电   情感天地   职场女性   职场礼仪   职场新人
报告总结   述职报告 工作总结 调查报告 工作汇报 计划方案 个人总结 社会实践 规章制度 调研报告 
  实习报告 考察报告 辞职报告 
演讲发言   竞职演说   就职演说   精彩演说   爱国演讲   英语演讲   十七大演讲   安全生产演讲稿   
节日祝福   重阳节 国庆节 教师节 中秋节 情人节 七夕节 劳动节 妇女节 清明节 愚人节 春节 元旦 圣诞节  儿童节  端午节 母亲节 新婚祝福 生日祝福 
讲话致辞   开业开幕   会议主持   庆典致辞   会议发言   党风廉政   党政报告   贺电慰问   婚丧嫁娶   思想宣传
法律常识   基本常识   法律文书   权益常识   劳动保障   婚姻继承   民事诉讼   刑事诉讼   
党建材料   入党申请   思想学习   党性分析   思想汇报   转正申请   民主生活   党委党建   入团申请   申报材料
求职简历   个人简历   求职自荐   求职谋略   面试技巧   求职英语   自我鉴定   英文简历   简历封面
心得体会   心得体会   经验交流   读后感   
时政热点   和谐社会   先进性教育   新农村建设   十七大   八荣八耻   科学发展观   劳动合同法   
人际沟通   社交技巧   社交礼仪   口才技巧   谈话技巧   演讲技巧   
营销技巧   电话销售   网络销售   推销技巧   促销技巧   销售口才   营销手段   销售技巧   谈判技巧   

“ 修改大型 XML 文件的有效方法”来源于网络,版权归作者所有!勿用于商业用途。

.NET技术

ASP技术
PHP技术
JSP技术
.NET技术
服务器技术
数据库开发
其它类

本类阅读TOP10

·数据库的连接串(中文)
·DES(Data Encryption Standard)加密解密整理
·利用Jmail发送和接收邮件(C#)
·.NET Framework 中多语言支持的实现
·动态菜单
·.NET 框架类库(上)
·C#中的事件
·微软.NET战略和ASP.NET简介(1)
·加密与解密
·ASP.NET中的代码分离

广告


关于本站|服务条款|广告服务|客服中心|发布文章|网站留言