.NET基础示例系列之二十二:Xml操作简明手册

1Xml文档示例(xmlsample.xml):

 

Code
<?xml version="1.0" encoding="iso-8859-1" ?>
<music>
  
<song title="Oh,girl">
    
<artist>The Chi-lites</artist>
    
<genre>Soul</genre>
    
<album>A lonely man</album>
    
<year>1972</year>
  
</song>
  
<song title="What if">
    
<artist>Babyface</artist>
    
<genre>R&amp;B</genre>
    
<album>unknown</album>
    
<year></year>
  
</song>
  
<song title="How come,how long">
    
<artist>Babyface</artist>
    
<genre>R&amp;B</genre>
    
<album>The essential babyface</album>
    
<year>2001</year>
  
</song>
  
<song title="Drama,love &amp;'lationship">
    
<artist>Babyface</artist>
    
<genre>R&amp;B</genre>
    
<album>Grown and sexy</album>
    
<year>2005</year>
  
</song>
  
<song title="Burning">
    
<artist>Maria Arredondo</artist>
    
<genre>Pop</genre>
    
<album>Not going under</album>
    
<year>2004</year>
  
</song>
  
<song title="Run">
    
<artist>Leona Lewis</artist>
    
<genre>Pop</genre>
    
<album>Unknown</album>
    
<year>2008</year>
  
</song>
  
<song title="Best thing">
    
<artist>Usher</artist>
    
<genre>R&amp;B</genre>
    
<album>Usher</album>
    
<year>2008</year>
  
</song>
  
<song title="Hurt">
    
<artist>Christina Aguilera</artist>
    
<genre>Blues</genre>
    
<album>Back to basics</album>
    
<year>2004</year>
  
</song>
  
<song title="Shape of my heart">
    
<artist>Sting</artist>
    
<genre>Pop</genre>
    
<album>Shape of my heart</album>
    
<year></year>
  
</song>
</music>

 

现在xml遍地都是,没见过猪跑,也吃过猪肉。xml文档本身,这里只做一个简单的介绍,后面主要是介绍C#操作xml的一些备忘(我自己只是偶尔会用到,所以常常忘记,需要重新查,所以写下来,以志不忘)。

XmleXtensive Makeup Language,超文本标记语言,与HTML类似,不同的是其根本目的是用来传输数据,而不是用于显示。

 

xml相关的几个概念:

*文档声明(Document declaration):

<?xmlversion="1.0"encoding="iso-8859-1" ?>

Xml文档的第一行即所谓的文档声明,告诉你这是一个xml文档。

 

*元素(Element):

<artist>The Chi-lites</artist>

开始标签、相应结束标签以及所包含的内容,整个构成一个“元素”。

 

*标签(Label):

针对上面所举元素,<artist></artist>即所谓的标签。

 

*属性(Attribute):

针对元素“song”,包含属性“title”。

 

还有向个小细节:

*元素的标签是大小写敏感的。

*Xml文档必须有一个根元素。

*Xml的属性值必须加双引号。

*特殊字符:

<(小于),替换为&lt;

>(大于),替换为&gt;

&,替换为&amp;

(单引号),替换为&apos;

(双引号),替换为&quot;

 

还有一些关于名称空间、以及CDATA区段等知识,有兴趣可以查看W3C文档,或者可以看看这个网站上的教程:http://www.w3school.com.cn/x.asp,上面有很详细的介绍。

 

 

2)如何创建一个xml文档

由于xml实质也只是一个文本文件,所以最简单你可以直接使用System.IO下的类生成一个文件,并存储成xml文件,当然,你需要手动保证该文件形式良好,比如必须有根元素、必须有关闭标签、必须正确嵌套等等。

 

如果你懒得自己去想文件的形式,可以使用System.Xml下的类。

 

Code
XmlDocument xdoc = new XmlDocument();
XmlDeclaration xdcl 
= xdoc.CreateXmlDeclaration("1.0""iso-8859-1""");
xdoc.AppendChild(xdcl);
//XmlNode xnode = xdoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
//xdoc.AppendChild(xnode);

//Of course you can use CreateNode here(with the XmlNodeType.Element),
//so no more questions about 'what difference between this 2 methods?',
XmlElement root = xdoc.CreateElement("music");
xdoc.AppendChild(root);

XmlElement xelm 
= xdoc.CreateElement("song");
xelm.SetAttribute(
"title""Oh,girl");
xelm.InnerText 
= "Oh,girl,i'd be in trouble if you left me now";
root.AppendChild(xelm);
try
{
    xdoc.Save(
"xmlsample-1.xml");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

结果:

Code
<?xml version="1.0" encoding="iso-8859-1"?>
<music>
  
<song title="Oh,girl">Oh,girl,i'd be in trouble if you left me now</song>
</music>

 

由于像XmlDeclarationXmlElement这些类都继承自XmlNode,故CreateNode()方法是最通用的,可以通过使用XmlNodeType来生成不同类型的节点。

另外,往元素中插入文本,使用的属性是“InnerText”。

 

方法二:

XmlDocument还有一个LoadXml()方法,实际上跟一行一行写入文本没区别,就是预先写好xml,并把它作为字符串传给LoadXml()方法。

 

方法三:

如果你手头有一个DataTable,还可以使用DataTable.WriteXml()方法。

 

Code
DataTable dt = new DataTable("music");
dt.Columns.Add(
"title"typeof(string));
dt.Columns.Add(
"artist");
dt.Columns.Add(
"genre");
dt.Columns.Add(
"album");
//
dt.Rows.Add("Oh,girl""The Chi-lites""Soul""A lonely man");
dt.Rows.Add(
"What if""Babyface""R&B""Unknown");
dt.AcceptChanges();
//
dt.WriteXml("xmlsample-2.xml");

结果:

 

Code
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
  
<music>
    
<title>Oh,girl</title>
    
<artist>The Chi-lites</artist>
    
<genre>Soul</genre>
    
<album>A lonely man</album>
  
</music>
  
<music>
    
<title>What if</title>
    
<artist>Babyface</artist>
    
<genre>R&amp;B</genre>
    
<album>Unknown</album>
  
</music>
</DocumentElement>

 

 

3)读取、查找

当你手头有一个xml文件后,可以使用XmlDocument.Load()方法将其加载进来以便处理,所以“读取”没有什么可说的。而“查找”操作往往涉及XPath,这里只是我认为的比较常用到的查找操作,XPath这玩意实在是很强大很暴力。

 

回头看示例文档xmlsample.xml,我们可能遇到这样的需求:

A)查找歌曲“Hurt”的演唱者?

B)查找流派为“R&B”的歌曲名称?

C)查找发行年份在2004以前的歌曲的演唱者?

D)倒数第二首歌的歌曲名称?

 

针对上述问题,你当然可以通过递归遍历各结点来查找,不过使用XPath将是更为高效的方案:

问题(A 

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//    
XmlNodeList xnl = doc.SelectNodes("/music/song[@title='Hurt']/artist");
foreach (XmlNode n in xnl)
{
    Console.WriteLine(n.InnerText);
}

(以“/”起始的路径必定是绝对路径,即从根元素起。而对属性的引用前面要加“@”)

 

问题(B

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNodeList xnl = doc.SelectNodes("/music/song[genre='R&B']");
foreach (XmlNode n in xnl)
{
    
if (n is XmlElement)
    {
        Console.WriteLine(((XmlElement)n).GetAttribute(
"title"));
    }
}

 (不同于对属性的引用,对子节点的引用不需要使用“@”)

 

问题(C

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNodeList xnl = doc.SelectNodes("/music/song[year<2004]/artist");
foreach (XmlNode n in xnl)
{
    Console.WriteLine(n.InnerText);
}

(数值一样可以比较。)

 

问题(D

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNode n = doc.SelectSingleNode("/music/song[last()-1]");
if (n is XmlElement)
{
    Console.WriteLine(((XmlElement)n).GetAttribute(
"title"));
}

(具有一系列的内置函数,如last()position()等等)

 

Ps

如何实现XPath查找时忽略大小写?

例如示例文档中的“专辑”一栏中,有时将未知写着“unknown”,有的写着“Unknown”,如何将它们都查询出来?

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNodeList xnl = doc.SelectNodes("/music/song[translate(album,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='unknown']");
foreach (XmlNode n in xnl)
{
    
if (n is XmlElement)
    {
        Console.WriteLine(((XmlElement)n).GetAttribute(
"title"));
    }
}

(使用translate()函数将其先转化为小写后再比较。)

 

 

4)修改

在完成了第三小节的查找定位之后,修改操作实际上就比较简单了。使用的方法不外乎:

RemoveChild()  删除节点

AppendChild()  添加节点

SetAttribute()  设置属性

InsertAfter(),InsertBefore()  类似于AppendChild(),但是可以更精确地指定要插入的位置,因为AppendChild()中是简单地追加。

 

值得一提的是ImportNode()方法,比如我们想将倒数第二首歌曲“Hurt”的所有信息复制一遍追加到文档的末尾,如果我们这么写:

 

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNode n = doc.SelectSingleNode("/music/song[last()-1]");
doc.DocumentElement.AppendChild(n);
//
doc.Save("xmlsample.xml");

 

上面的代码得到的效果类似于“剪切”,就是原来倒数第二首歌被放到最末尾了。想要实现“拷贝”的效果,我们可以这么写:

ImportNode()方法对于不同的xml文档中拷贝节点尤其有用。

Code
XmlDocument doc = new XmlDocument();
doc.Load(
"xmlsample.xml");
//
XmlNode n = doc.SelectSingleNode("/music/song[last()-1]");
doc.DocumentElement.AppendChild(doc.ImportNode(n,
true));
//
doc.Save("xmlsample.xml");

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值