提起XML,并不陌生,它随处可见,例如,网站的web.config,RSS.xml.可自定义节点,还可充当数据库,可是如果真的静心来看看它,却只知道是类似于HTML的节点标签文件,可以这样用可以那样用,花样繁多,并不是非常的了解他。
XML,可扩展标记语言(Extensible Markup Language, XML),作为一个小菜鸟,可能并无法从定义上是真正的了解XML是什么,或许我们可以从他的用途上去认识,这样比记忆那些空洞的定义更有帮助。下面是XML的几种招人喜爱的用途,主要分为文档型和数据型:(维基百科)
HTML与XML之间的关系
1、XML可以视作对HTML的补充。
2、HTML 的设计目标是显示数据并集中于数据外观,而XML的设计目标是描述数据并集中于数据的内容。
3、与HTML相似,XML不进行任何操作。虽然XML标记可用于描述订单之类的项的结构,但它不包含可用于发送或处理该订单以及确保按该订单交货的任何代码,其他人必须编写代码来实际对XML格式的数据执行这些操作。与 HTML 不同,XML 标记由架构或文档的作者定义,并且是无限制的。HTML 标记则是预定义的;HTML 作者只能使用当前 HTML 标准所支持的标记。
4、XML 标记由架构或文档的作者定义,并且是无限制的。HTML 标记则是预定义的;HTML 作者只能使用当前 HTML 标准所支持的标记。
总之,XML实际是一种抽象的语言,只是不如常用的传统语言那么具体。
为了涵盖XML的扩展用法,.NET Framework包含了System.XML命名空间,这个命名空间包含了许多处理XML的类。增删修改有关的类有以下几个:
XMLReader(这是一个抽象类),它拥有三个常用子类 | XMLNodeReader |
XMLTextReader | |
XMLValidatingReader | |
XMLWriter,同XMLReader一样,它也是一个抽象类,有两个常用子类 | XMLTextWriter |
XmlQueryWriter | |
DOM模型 | XmlLinkedNode (有子类XmlElement) |
XmlDocument | |
XmlAttribute | |
XmlEntity |
操作XML,首先我们先写个XML的Demo:Account.xml,如下所示:
<Server> <Accounts> <Account> <Email>[email protected]</Email> <IsAdmin>True</IsAdmin> <Password>123</Password> </Account> <Account>
</Accounts> </Server>
将它存在指定路径下,我本地存放路径为 C:\test\Accounts.xml
public class Account { public string Email { get; set; } public bool IsAdmin { get; set; } public string Password { get; set; } }
2. 创建class AccountXML,这个类中有5个静态方法,主要是针对account.xml的操作。
public static XmlDocument loadXml() { XmlDocument Doc = new XmlDocument(); //check the path try { Doc.Load("C:\\test\\Accounts.xml"); } catch (Exception e) { XmlDocument newDoc = new XmlDocument(); XmlElement root = newDoc.CreateElement("Server"); newDoc.AppendChild(root); XmlElement childAccounts = newDoc.CreateElement("Accounts"); root.AppendChild(childAccounts); newDoc.Save("C:\\test\\Accounts.xml"); Doc.Load("C:\\test\\Accounts.xml"); } return Doc; }
//read server account.xml public static List<Account> xmlReader() { List<Account> acccountList = new List<Account>(); XmlDocument doc = loadXml(); XmlNodeList nodeList= doc.GetElementsByTagName("Account"); Account account = new Account(); foreach (XmlNode node in nodeList) { //assign values account.Email = node.SelectSingleNode("Email").InnerText.ToString(); account.IsAdmin = node.SelectSingleNode("IsAdmin").InnerText == "True"; account.Password = node.SelectSingleNode("Password ").InnerText.ToString(); acccountList.Add(account); } return acccountList; }
//write server account.xml public static void xmlWriter(Account acc) { XmlDocument xmlDoc = loadXml(); XmlNode accountsNode = xmlDoc.SelectSingleNode("Server/Accounts"); XmlElement accountNode = xmlDoc.CreateElement("Account"); XmlElement email = xmlDoc.CreateElement("Email"); XmlElement isAdmin = xmlDoc.CreateElement("IsAdmin"); XmlElement password = xmlDoc.CreateElement("Password"); email.InnerXml = acc.Email.ToString(); isAdmin.InnerXml = acc.IsAdmin.ToString(); password.InnerXml = acc.Password.ToString(); accountNode.AppendChild(email); accountNode.AppendChild(isAdmin); accountNode.AppendChild(password); accountsNode.AppendChild(accountNode); //save doc try { xmlDoc.Save("C:\\test\\Accounts.xml"); } catch (Exception save) { throw save; } }
xmlUpdate(Account acc)方法,这个方法有一个Account对象参数,如果该对象不存在,它会被写入xml ,若存在,则不被写入,注意:这个方法里用来判别对象是否存在的对比参数为Email属性
public static void xmlUpdate(Account acc) {
XmlDocument xmlDoc = loadXml();
XmlNodeList accountList = xmlDoc.SelectSingleNode("Server/Accounts").ChildNodes;
foreach (XmlNode account in accountList) {
//if account exists
if (acc.Email.ToString() == account.SelectSingleNode("Email").InnerXml.ToString())
{
XmlElement accountElement = (XmlElement)account;
XmlNodeList accountChild = account.ChildNodes;
foreach (XmlNode child in accountChild)
{
XmlElement eleChild = (XmlElement)child;
switch (eleChild.Name)
{
case "EMAIL":
eleChild.InnerText = acc.Email;
break;
case "IsAdmin":
eleChild.InnerText = acc.IsAdmin.ToString();
break;
case "Password":
eleChild.InnerText = acc.Password.ToString();
break;
}
}
xmlDoc.Save("C:\\test\\Accounts.xml");
}
else {
AccountXML.xmlWriter(acc);
}
}
}
xmlDelte(Account acc)这个方法有一个Account对象参数,该对象将会被删除
public static void xmlDelte(Account acc) { XmlDocument xmlDoc = loadXml(); XmlNodeList accountList = xmlDoc.SelectSingleNode("Server/Accounts").ChildNodes; foreach (XmlNode account in accountList) { if (acc.Email== account.SelectSingleNode("Email").InnerXml) { XmlElement accountElement = (XmlElement)account; //accountElement.RemoveAll(); accountElement.ParentNode.RemoveChild(account); //account.ParentNode.RemoveChild(account); } } xmlDoc.Save("C:\\test\\Accounts.xml"); } }
我们将在Main方法中进行操作:
class Program { static void Main(string[] args) { Account a = new Account() { Email="[email protected]",IsAdmin=false, Password="123"}; AccountXML.xmlWriter(a); //read List<Account> b = AccountXML.xmlReader(); a = b[0]; Console.WriteLine("I am readed by the method AccountXML.xmlReader()"); Console.WriteLine("Password: "+a.Password); Console.WriteLine("Email: "+a.Email); Console.WriteLine("IsAdmin: "+a.IsAdmin); Console.WriteLine(); //update a.Password = "I am hungry"; AccountXML.xmlUpdate(a); Console.WriteLine("After update object a: "); Console.WriteLine("Password: " + a.Password); Console.WriteLine("Email: " + a.Email); Console.WriteLine("IsAdmin: " + a.IsAdmin); Console.WriteLine(); //Delete Console.WriteLine("Before delete object a, the length of List<Account> b is "+b.Count); AccountXML.xmlDelte(a); b = AccountXML.xmlReader(); Console.WriteLine("After delete object a, the length of List<Account> b is " + b.Count); Console.ReadKey(); } }
试验结果完全通过,如下所示:
Note: 由于只是做test操作,路径信息hardCode写入方法中,实际工作中,可将此信息作为全局参数抽取出来,以便更加方便快捷操作xml。