第一部分 什么是XML?
XML, Extensible Markup Language ,可扩展标记语言,主要用途是描述和交换数据。它的一个用处是配置文件,用来保存数据库连接字符串、端口、IP、日志保存路径等参数。我们可以使用文本文件来保存文件,使用 key = value, key2 = value2 ,...... 的方式来保存数据。这样做的坏处是结构比较不规矩,读取起来也不方便,需要自行编写一长串的if / else 语句。为了解决这些问题,我们可以使用XML。
XML定义了一组规则,即它的格式和操作方法。下面介绍几种基本规则:
1、文档声明
文档声明属于XML处理指令。如<?xml version="1.0" encoding="utf-8" ?>,说明了XML的版本和字符编码。
2、处理指令
处理指令以<?开始,以?>结束,用于将指令传递给XML解析器。例如<?xml-stylesheet type="text/css" href="main.css" ?>指令用于在XML中链接样式表。
3、节点(Node),元素(Element),标记(Tag)。
元素是节点的子集,称为元素节点,文档声明可以是文档声明节点。节点包括了XML几乎所有内容。元素是XML主要结构,元素的形式是标记。例如ip可能是一个元素,而<ip>、</ip>则是标记。
4、有且只有一个文档元素(Document Element)。
5、标记不能交错嵌套。
6、标记必须闭合。可以使用单标记闭合<tag />,也可以使用两个标记来闭合<tag></tag>。
7、大小写敏感。
8、元素可以包含属性(Attribute)、文本(text)。
9、预定义实体引用。
其实就是转义符。比如<的实体引用是<。
10、CDATA
位于CDATA中的文本不要求满足XML的规则。其格式为<tag><![CDATA[ 1<X<10]]></tag>,这里我们不需要对[]里面的<进行转义了。
11、文档类型声明。
格式为<!DOCTYPE rootElement>,rootElement是我们定义的根节点名称。
12、自定义引用。
类似于常量声明,位于文档类型声明中。格式为 : <!DOCTYPE rootElement [<!ENTITY BRUCE "布鲁斯少爷">]>。现在引用 &BRUCE; 相当于 布鲁斯少爷 了。
13、命名空间。
命名空间主要目的是为了避免标记重名。在自己使用自定义的XML时,几乎用不到命名空间。它的格式是 xmlns="myNamespace"。还可以给命名空间加上前缀。
XML有可能是非法的,尽管它看起来正确。这就引入了XML有效性验证。比如说,我们有一个date属性,应该接受一个DateTime类型,结果第三方使用者却提供了一个字符串。我们可以预先定义好文档的结构、标记、属性、属性值、文本值等信息,相当于该XML的元数据,通过这个元数据来对XML进行合法性验证。这种方法也被制定成规范,包括XSD,DTD,XDR等。同样,自用自定义XML几乎用不到这些验证。
第二部分 操作XML
先使用XMLWriter生成一个XML文档。其实直接写更方便些。
using UnityEngine; using System.Collections; using System.Xml; public class GenXML : MonoBehaviour { void Start() { string filePath =Application.dataPath +@"\movieList.xml"; XmlWriterSettings settings = new XmlWriterSettings (); settings.Encoding = System.Text.Encoding.UTF8; settings.Indent = true; settings.IndentChars = "\t"; settings.OmitXmlDeclaration = false; XmlWriter writer = XmlWriter.Create (filePath, settings); writer.WriteStartDocument (); writer.WriteDocType ("movieList", null, null, null); writer.WriteStartElement ("movieList"); writer.WriteComment ("新上映电影信息"); writer.WriteStartElement ("movie"); writer.WriteAttributeString ("id", "1"); writer.WriteAttributeString ("title", "魔境仙踪"); writer.WriteAttributeString ("director", "Sam`Rayme"); writer.WriteAttributeString ("release", "2013-3-28"); writer.WriteElementString ("starring", "james`franco"); writer.WriteStartElement ("genreList"); writer.WriteElementString ("genre", "冒险"); writer.WriteElementString ("genre", "家庭"); writer.WriteElementString ("genre", "奇幻"); writer.WriteEndElement (); writer.WriteEndElement (); writer.WriteStartElement ("movie"); writer.WriteAttributeString ("id", "2"); writer.WriteAttributeString ("title", "虎胆龙威5"); writer.WriteAttributeString ("director", "John`Moor"); writer.WriteAttributeString ("release", "2013-3-14"); writer.WriteElementString ("starring","BRUCE LEE"); writer.WriteStartElement ("genreList"); writer.WriteElementString ("genre", "动作"); writer.WriteElementString ("genre", "犯罪"); writer.WriteElementString ("genre", "惊悚"); writer.WriteEndElement (); writer.WriteEndElement (); writer.WriteEndElement (); writer.WriteEndDocument (); writer.Flush (); writer.Close (); } }
这就是生成的XML文档;
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE movieList> <movieList> <!--新上映电影信息--> <movie id="1" title="魔境仙踪" director="Sam`Rayme" release="2013-3-28"> <starring>james`franco</starring> <genreList> <genre>冒险</genre> <genre>家庭</genre> <genre>奇幻</genre> </genreList> </movie> <movie id="2" title="虎胆龙威5" director="John`Moor" release="2013-3-14"> <starring>BRUCE LEE</starring> <genreList> <genre>动作</genre> <genre>犯罪</genre> <genre>惊悚</genre> </genreList> </movie> </movieList>
使用XMLReader读取所有节点:
using UnityEngine; using System.Collections; using System.IO; using System.Xml; public class ReadXML : MonoBehaviour { void Start(){ XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; settings.ProhibitDtd = false; string filePath =Application.dataPath +@"\movieList.xml"; XmlReader reader = XmlReader.Create (filePath, settings); while(reader.Read()) { string indent = new string(' ',reader.Depth*3); string line = string.Format("{0}{1} | {2} - {3}",indent,reader.NodeType,reader.Name,reader.Value); Debug.Log(line); line = ""; if(reader.NodeType==XmlNodeType.Element&&reader.HasAttributes){ for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); line+=string.Format("{0}[{1} , {2}]\r\n",indent,reader.Name,reader.Value); } Debug.Log(line); } } reader.Close (); } }
使用XMLDocument为XML文档增加一些新内容。
//使用XMLDocument修改XML XmlDocument xdoc = new XmlDocument (); xdoc.Load (filePath); XmlElement movie = xdoc.CreateElement ("movie"); XmlAttribute attr = xdoc.CreateAttribute ("id"); attr.Value = "4"; movie.Attributes.Append (attr); attr = xdoc.CreateAttribute ("title"); attr.Value = "电锯惊魂"; movie.Attributes.Append (attr); attr = xdoc.CreateAttribute ("director"); attr.Value = "ROCK MAN"; movie.Attributes.Append (attr); attr = xdoc.CreateAttribute ("release"); attr.Value = "2013-4-12"; movie.Attributes.Append (attr); XmlElement starring = xdoc.CreateElement ("starring"); starring.InnerText = "DICK Fur"; movie.AppendChild (starring); XmlElement genreList = xdoc.CreateElement ("genreList"); XmlElement genre = xdoc.CreateElement ("genre"); genre.InnerText = "恐怖"; genreList.AppendChild (genre); genre = xdoc.CreateElement ("genre"); genre.InnerText = "血腥"; genreList.AppendChild (genre); movie.AppendChild(genreList); XmlElement root = xdoc.DocumentElement; root.AppendChild(movie); xdoc.Save (Application.dataPath+@"\movieList2.xml");
这是新添加的部分。
<movie id="4" title="电锯惊魂" director="ROCK MAN" release="2013-4-12"> <starring>DICK Fur</starring> <genreList> <genre>恐怖</genre> <genre>血腥</genre> </genreList> </movie>
使用XPath访问并修改XML节点。
//使用XPath访问XML节点 XmlDocument xmlDoc = new XmlDocument (); xmlDoc.Load (filePath); XmlElement root = xmlDoc.DocumentElement; XmlNode movie = root.SelectSingleNode ("movie[@id=2]"); XmlNode titleAttr = movie.SelectSingleNode ("@title"); titleAttr.Value = "龙胆虎威8:叱咤风云"; XmlNode starring = movie.SelectSingleNode ("starring"); starring.InnerText = starring.InnerText + "/Youth Gill"; XmlNode genre = movie.SelectSingleNode ("genreList/genre[3]"); XmlNode genreList = movie.SelectSingleNode ("genreList"); genreList.RemoveChild (genre); xmlDoc.Save (Application.dataPath +@"\movieList3.xml");
这是修改后的内容。
<movie id="2" title="龙胆虎威8:叱咤风云" director="John`Moor" release="2013-3-14"> <starring>BRUCE LEE/Youth Gill</starring> <genreList> <genre>动作</genre> <genre>犯罪</genre> </genreList> </movie>
此外,还可以对XML进行验证和转换。因为用的不多,就不写了。