c#XML操作

1.XPath语法 在C#中使用XPath示例

XPath可以快速定位到Xml中的节点或者属性。XPath语法很简单,但是强大够用,它也是使用xslt的基础知识。

示例Xml:


 
  
   100 
   this is a black cat
   
   
  80 
   this is a white cat
  
      80  
  this is a yellow cat 
   
    100  
  this is a black dog       
 80 
   this is a white dog   
     80  
  this is a yellow dog  




XPath的语法:

1. XPath中的符号

符号

说明

示例

示例说明

/

表示从根节点开始选择

/pets

选择根节点pets

表示节点和子节点之间的间隔符

/pets/dog

选择pets节点下的dog节点

//xx

表示从整个xml文档中查找,而不考虑当前节点位置

//price

选择文档中所有的price节点

.

单个英文半角句点表示选择当前节点

/pets/.

选择pets节点

..

双点,表示选择父节点

/pets/dog[0]/..

表示pets节点,也就是第一个dog节点的父节点

@xx

表示选择属性

//dog/@color

表示选择所有dog节点的color属性集合

[…]

中括号表示选择条件,括号内为条件

//dog[@color=’white’]

所有color为white的dog节点

//dog[/price<100]

所有price字节点值小于100的dog节点

中括号内数字为节点索引,类似c#等语言中的数组,数组下标是从1开始的

//dog[1]

第1个dog节点

//dog[last()]

最后一个dog节点,last()是xPath内置函数

|

单竖杠表示合并节点结合

//dog[@color=’white’] | //cat[@color=’white’]

color属性为white的dog节点和color属性为white的cat节点

*

星号表示任何名字的节点或者属性

//dog/*

表示dog节点的所有子节点

//dog/@*

表示dog节点的所有属性节点

2. XPath数学运算符
+  加号表示加
- 表示数字相减
* 表示乘以
div 表示除以,这里数学上的除号/已经被用作节点之间分隔符了
mod 表示取余
3. XPath逻辑运算符
= 等于,相当于c#中的 ==
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
and 并且 与关系
or 或者 或关系
4.  XPath Axes 从字面翻译这个是XPath轴的意思,但根据我的理解这个翻译成XPath节点关系运算关键字更合适,就是一组关键字加上::双冒号表示和当前节点有关系的一个或者一组节点.
使用语法: axisname::nodetest[predicate] 即轴名字::节点名字[取节点条件]
具体说明如下:

关键字

说明

示例

示例说明

ancestor

当前节点的父祖节点

ancestor::pig

当前节点的祖先节点中的pig节点

ancestor-or-self

当前节点以及其父祖节点

ancestor::pig

 

attribute

当前节点的所有属性

attribute::weight

相当于@weight,attribute::和@是等价的

child

当前节点的所有字节点

child::*[name()!=’price’]

选择名字不是price的子节点

descendant

子孙节点

descendant::*[@*]

有属性的子孙节点

descendant-or-self

子孙节点以及当前节点

descendant-or-self::*

 

following

Xml文档中当前节点之后的所有节点

following::*

 

following-sibling

当前节点的同父弟弟节点

following-sibling::

 

preceding

Xml文档中当前节点之前的所有节点

preceding::*

 

namespace

选取当前节点的所有命名空间节点

namespace::*

 

parent

当前节点的父节点

parent::

相当于双点..

preceding-sibling

当前节点之后的同父兄节点

preceding-sibling::*

 

self

当前节点

self::*

相当于单点.


5. 常用的XPath函数介绍:
在XPath表达式中常用的函数有下面两个:
position() 表示节点的序号例如 //cat[position() = 2] 表示取序号为2的dog节点
last() 表示取最后一个节点 //cat[last()] 
name() 表示当前节点名字 /pets/*[name() != 'pig'] 表示/pets下名字不是pig的子节点
XPath的函数还有很多,包括字符串函数,数字函数和时间函数等,具体可以参考w3的网站。
以上是XPath的语法,下面我们看下如何在.Net中使用XPath
在.Net中可以通过XPathDocument或者XmlDocument类使用XPath。XPathDocument是只读的方式定位Xml节点或者属性文本等,而XmlDocument则是可读写的。
如下代码示例展示了如何使用XPathDocument和XmlDocument
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.XPath;
using System.Xml;

namespace UseXPathDotNet
{
    class Program
    {
        static void Main(string[] args)
        {
            UseXPathWithXPathDocument();

            UseXPathWithXmlDocument();

            Console.Read();
        }

        static void UseXPathWithXmlDocument()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("http://www.cnblogs.com/yukaizhao/rss");
            //使用xPath选择需要的节点
            XmlNodeList nodes = doc.SelectNodes("/rss/channel/item[position()<=10]");
            foreach (XmlNode item in nodes)
            {
                string title = item.SelectSingleNode("title").InnerText;
                string url = item.SelectSingleNode("link").InnerText;
                Console.WriteLine("{0} = {1}", title, url);
            }
        }

        static void UseXPathWithXPathDocument()
        {
            XPathDocument doc = new XPathDocument("http://www.cnblogs.com/yukaizhao/rss");
            XPathNavigator xPathNav = doc.CreateNavigator();
            //使用xPath取rss中最新的10条随笔
            XPathNodeIterator nodeIterator = xPathNav.Select("/rss/channel/item[position()<=10]");
            while (nodeIterator.MoveNext())
            {
                XPathNavigator itemNav = nodeIterator.Current;
                string title = itemNav.SelectSingleNode("title").Value;
                string url = itemNav.SelectSingleNode("link").Value;
                Console.WriteLine("{0} = {1}",title,url);
            }

        }
    }
}



XPath使用示例,请看下面的代码注释 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace UseXPath1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml = @"

  
    100
    this is a black cat
  
  
    80
    this is a white cat
  
  
    110
    this is a yellow cat
  


  
    114
    this is a black dog
  
  
    80
    this is a white dog
  
  
    80
    this is a yellow dog
  

    
    8000
    this is a white pig    
    
";

            using (StringReader rdr = new StringReader(xml))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(rdr);

                //取所有pets节点下的dog字节点
                XmlNodeList nodeListAllDog = doc.SelectNodes("/pets/dog");

                //所有的price节点
                XmlNodeList allPriceNodes = doc.SelectNodes("//price");

                //取最后一个price节点
                XmlNode lastPriceNode = doc.SelectSingleNode("//price[last()]");

                //用双点号取price节点的父节点
                XmlNode lastPriceParentNode = lastPriceNode.SelectSingleNode("..");

                //选择weight*count=40的所有动物,使用通配符*
                XmlNodeList nodeList = doc.SelectNodes("/pets/*[@weight*@count=40]");

                //选择除了pig之外的所有动物,使用name()函数返回节点名字
                XmlNodeList animalsExceptPigNodes = doc.SelectNodes("/pets/*[name() != 'pig']");
               

                //选择价格大于100而不是pig的动物
                XmlNodeList priceGreaterThan100s = doc.SelectNodes("/pets/*[price div @weight >10 and name() != 'pig']");
                foreach (XmlNode item in priceGreaterThan100s)
                {
                    Console.WriteLine(item.OuterXml);
                }

                //选择第二个dog节点
                XmlNode theSecondDogNode = doc.SelectSingleNode("//dog[position() = 2]");

                //使用xpath ,axes 的 parent 取父节点
                XmlNode parentNode = theSecondDogNode.SelectSingleNode("parent::*");

                //使用xPath选择第二个dog节点前面的所有dog节点
                XmlNodeList dogPresibling = theSecondDogNode.SelectNodes("preceding::dog");

                //取文档的所有子孙节点price
                XmlNodeList childrenNodes = doc.SelectNodes("descendant::price");
            }

            Console.Read();
        }
    }
}



本文转载自http://www.cnblogs.com/yukaizhao/archive/2011/07/25/xpath.html 




2.通过XmlDocument读写Xml文档

有如下一段Xml:


  
  
    
      
        
          
              
    

      
        
          
        
      
    
  

2.如何使用XmlDocument读取Xml

我要用一段代码遍历所有Student,并打印Student的所有属性和子节点的值
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace XmlExample
{
    class Program
    {
        static void Main(string[] args)
        {
            string xmlFilePath = @"X:\about.net\example\XmlExample\1.xml";
            XmlDocument doc = new XmlDocument();
            doc.Load(xmlFilePath);

            //使用xpath表达式选择文档中所有的student子节点
            XmlNodeList studentNodeList = doc.SelectNodes("/students/student");
            if (studentNodeList != null)
            {
                foreach (XmlNode studentNode in studentNodeList)
                {
                    //通过Attributes获得属性名字为name的属性
                    string name = studentNode.Attributes["name"].Value;
                    Console.WriteLine("Student:" + name);

                    //通过SelectSingleNode方法获得当前节点下的courses子节点
                    XmlNode coursesNode = studentNode.SelectSingleNode("courses");

                    //通过ChildNodes属性获得courseNode的所有一级子节点
                    XmlNodeList courseNodeList = coursesNode.ChildNodes;
                    if (courseNodeList != null)
                    {
                        foreach (XmlNode courseNode in courseNodeList)
                        {
                            Console.Write("\t");
                            Console.Write(courseNode.Attributes["name"].Value);
                            Console.Write("老师评语");
                            //通过FirstNode属性可以获得课程节点的第一个子节点,LastNode可以获得最后一个子节点
                            XmlNode teacherCommentNode = courseNode.FirstChild;
                            //读取CData节点
                            XmlCDataSection cdata = (XmlCDataSection)teacherCommentNode.FirstChild;
                            Console.WriteLine(cdata.InnerText.Trim());
                        }
                    }
                }
            }

            Console.Write("\r\nPress any key to continue....");
            Console.Read();
        }
    }
}

XmlDocument本身是从XmlNode继承的,读Xml节点可以通过FirstChild,LastChild,或者NextSibling,PreviousSibling读取单个节点,或者通过ChildNodes读取所有子节点。还可以使用XPath表达式使用SelectNodes(string xpath)或者SelectSingleNode(string xpath)读取单个或者多个符合条件的节点。
2.如何通过XmlDocument编辑Xml
同样是读取Xml中的xml例子,我们这次要用csharp代码生成xml,如下代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace WriteXml
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xmlDoc = new XmlDocument();
            //创建Xml声明部分,即
            xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes");

            //创建根节点
            XmlNode rootNode = xmlDoc.CreateElement("students");

            //创建student子节点
            XmlNode studentNode = xmlDoc.CreateElement("student");
            //创建一个属性
            XmlAttribute nameAttribute = xmlDoc.CreateAttribute("name");
            nameAttribute .Value = "张同学";
            //xml节点附件属性
            studentNode.Attributes.Append(nameAttribute);

           
            //创建courses子节点
            XmlNode coursesNode = xmlDoc.CreateElement("courses");
            XmlNode courseNode1 = xmlDoc.CreateElement("course");
            XmlAttribute courseNameAttr = xmlDoc.CreateAttribute("name");
            courseNameAttr.Value = "语文";
            courseNode1.Attributes.Append(courseNameAttr);
            XmlNode teacherCommentNode = xmlDoc.CreateElement("teacherComment");
            //创建Cdata块
            XmlCDataSection cdata = xmlDoc.CreateCDataSection("这是语文老师的批注");
            teacherCommentNode.AppendChild(cdata);
            courseNode1.AppendChild(teacherCommentNode);
            coursesNode.AppendChild(courseNode1);
            //附加子节点
            studentNode.AppendChild(coursesNode);

            rootNode.AppendChild(studentNode);
            //附加根节点
            xmlDoc.AppendChild(rootNode);

            //保存Xml文档
            xmlDoc.Save(@"d:\test.xml");

            Console.WriteLine("已保存Xml文档");


        }
    }
}
使用XmlDocument生成xml的要点在于使用xmlDocument的实例的CreateElement创建XmlNode或者通过CreateAttribute方法创建属性,并通过AppendChild方法附加xml节点,通过AppendAttribute附加Attribute到节点的属性集合。

本人转载自http://www.cnblogs.com/yukaizhao/archive/2011/07/19/csharp_xmldocument_access_xml.html


3.使用XmlReadrer读取xml

XmlDocument和XElement在读取Xml时要将整个Xml文档放到内存中去操作,这样做操作简单,但是很费内存和IO(可能是磁盘IO或者网络IO);而在有些场景下我们必须考虑尽可能节省内存和IO的开销,这时候就该XmlReader和XmlWriter出场了。

XmlReader读取Xml需要通过Read()实例方法,不断读取Xml文档中的声明,节点开始,节点内容,节点结束,以及空白等等,直到文档结束,Read()方法返回false。

如下读取Xml内容实例代码和注释说明

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
 
namespace UseXmlReader
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明StringReader传入Xml文本,作为XmlReader.Create的参数
            using (StringReader strRdr = new StringReader(@"

    I'm a Cat
    
"))
            {
                //通过XmlReader.Create静态方法创建XmlReader实例
                using (XmlReader rdr = XmlReader.Create(strRdr))
                {
                    //循环Read方法直到文档结束
                    while (rdr.Read())
                    {
                        Console.WriteLine("rdr.NodeType = " + rdr.NodeType);
                        //如果是开始节点
                        if (rdr.NodeType == XmlNodeType.Element) {
                            //通过rdr.Name得到节点名
                            string elementName = rdr.Name;
                             
                            Console.WriteLine(elementName + " element start");
                            if (elementName == "root") {
 
                            }
                            //读取到cat元素 这时rdr.Read()读取到的内容为
                            else if (elementName == "cat")
                            {
                                //可以通过中括号获得属性值
                                string colorVal = rdr["color"];
                                Console.WriteLine("\tcat's color is " + colorVal);
 
                                //读取到节点内文本内容
                                if(rdr.Read()) {
                                    //通过rdr.Value获得文本内容
                                    Console.WriteLine("\t cat said:" + rdr.Value);
                                }
                            }
                        }
                        else if (rdr.NodeType == XmlNodeType.EndElement)
                        {
                            //在节点结束时也可以通过rdr.Name获得节点名字
                            string elementName = rdr.Name;
                            Console.WriteLine(elementName + " element end");
                        }
                    }
                }
            }
 
            Console.Read();
        }
    }
}
如果觉得代码不明白,下面是一张读取顺序图,标明了读取顺序号和每次读取的内容,如下图所示:
c#XML操作_第1张图片
从图中可以看到XmlReader在读取这段Xml时:
第1次Read()读取的是Xml文档声明部分
第2次Read()读取的是声明后的空白
第3次Read()读取的是根节点root的开始标签
第4次Read()读取的是根节点开始后的空白
第5次Read()读取的是cat节点的开始部分,从左尖括号到右尖括号包括该节点的属性
第6次读取的是cat节点的内容
第7次读取的是cat节点的结束标签
第8次读取的是cat节点结束标签后的空白
第9次读取的是dog节点的开始部分,注意是从左尖括号开始到结束斜杠之前
第10次读取的是dog标签的结束/>
第11次读取的是dog标签结束后的空白
第12次读取的是root的结束标签

4.使用XmlWriter写Xml

假定创建了XmlWriter的实例变量xmlWriter,下文中将使用此实例变量写Xml

1.如何使用XmlWriter写Xml文档声明

// WriteStartDocument方法可以接受一个bool参数(表示standalone,是否为独立文档)或者不指定参数standalone保持默认值
xmlWriter.WriteStartDocument( false | true );

注意在使用WriteStartDocument方法后最好调用xmlWrite.WriteEndDocument()方法来关闭所有可能未关闭标签
2.如何使用XmlWriter写xml节点以及属性

//写节点
xmlWriter.WriteStartElement( "cat" );
//给节点添加属性
xmlWriter.WriteAttributeString( "color" , "white" );
//给节点内部添加文本
xmlWriter.WriteString( "I'm a cat" );
xmlWriter.WriteEndElement();

或者通过WriteElementString(string,string)方法写xml节点同时写下节点值,如下

//通过WriteElementString可以添加一个节点同时添加节点内容
xmlWriter.WriteElementString( "pig" , "pig is great" );

3.如何写CData

xmlWriter.WriteStartElement( "dog" );
//写CData
xmlWriter.WriteCData( "dog is dog" );
xmlWriter.WriteEndElement();

4.如何使用XmlWriter添加注释

xmlWriter.WriteComment( "this is an example writed by sedi " );

5.如何设置XmlWriter的输出格式,解决输出UTF-16问题
设置xml输出格式,需要通过XmlWriterSettings类,如下代码

XmlWriterSettings settings = new  XmlWriterSettings();
//要求缩进
settings.Indent = true ;
//注意如果不设置encoding默认将输出utf-16
//注意这儿不能直接用Encoding.UTF8如果用Encoding.UTF8将在输出文本的最前面添加4个字节的非xml内容
settings.Encoding = new  UTF8Encoding( false );
                 
//设置换行符
settings.NewLineChars = Environment.NewLine;

完整的代码示例如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
 
namespace UseXmlWriter
{
    class Program
    {
        static void Main(string[] args)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                //要求缩进
                settings.Indent = true;
                //注意如果不设置encoding默认将输出utf-16
                //注意这儿不能直接用Encoding.UTF8如果用Encoding.UTF8将在输出文本的最前面添加4个字节的非xml内容
                settings.Encoding = new UTF8Encoding(false);
                 
                //设置换行符
                settings.NewLineChars = Environment.NewLine;
 
                using (XmlWriter xmlWriter = XmlWriter.Create(ms, settings))
                {
 
                    //写xml文件开始
                    xmlWriter.WriteStartDocument(false);
                    //写根节点
                    xmlWriter.WriteStartElement("root");
                    //写字节点
                    xmlWriter.WriteStartElement("cat");
                    //给节点添加属性
                    xmlWriter.WriteAttributeString("color", "white");
                    //给节点内部添加文本
                    xmlWriter.WriteString("I'm a cat");
                    xmlWriter.WriteEndElement();
 
 
                    //通过WriteElementString可以添加一个节点同时添加节点内容
                    xmlWriter.WriteElementString("pig", "pig is great");
 
 
                    xmlWriter.WriteStartElement("dog");
                    //写CData
                    xmlWriter.WriteCData("dog is dog");
                    xmlWriter.WriteEndElement();
 
                    xmlWriter.WriteComment("this is an example writed by 玉开技术博客 http://www.cnblogs.com/yukaizhao ");
 
                    xmlWriter.WriteEndElement();
                    xmlWriter.WriteEndDocument();
 
                }
 
                //将xml内容输出到控制台中
                string xml = Encoding.UTF8.GetString(ms.ToArray());
                Console.WriteLine(xml);
            }
            Console.Read();
 
        }
    }
}

5.linq  to xml  操作XML

LINQ to XML提供了更方便的读写xml方式。前几篇文章的评论中总有朋友提,你为啥不用linq to xml?现在到时候了,linq to xml出场了。
.Net中的System.Xml.Linq命名空间提供了linq to xml的支持。这个命名空间中的XDocument,XElement以及XText,XAttribute提供了读写xml文档的关键方法。
1. 使用linq to xml写xml:
使用XDocument的构造函数可以构造一个Xml文档对象;使用XElement对象可以构造一个xml节点元素,使用XAttribute构造函数可以构造元素的属性;使用XText构造函数可以构造节点内的文本。
如下实例代码:
class Program
{
    static void Main(string[] args)
    {           
        var xDoc = new XDocument(new XElement( "root",
            new XElement("dog",
                new XText("dog said black is a beautify color"),
                new XAttribute("color", "black")),
            new XElement("cat"),
            new XElement("pig", "pig is great")));
 
        //xDoc输出xml的encoding是系统默认编码,对于简体中文操作系统是gb2312
        //默认是缩进格式化的xml,而无须格式化设置
        xDoc.Save(Console.Out);
 
        Console.Read();
    }
}

上面代码将输出如下Xml:


  dog said black is a beautify color
  
  pig is great

2. 使用linq to xml 读取xml
Linq是从集合中查询对象,在linq to xml中的集合是通过XElement的Elements(),Elements(string name),以及Descendants、DescendantsAndSelf、Ancestors、AncestorsAndSelf的几个重载方法中获得。
获得XElement集合之后,可以通过XElement的Attribute(string name)方法获得元素的属性值,可以通过XElement的Value属性获得节点的文本值;使用linq就可以方便的做查询,做筛选排序了
还是上例中的xml,我们要读取root的所有字节点,并打印出来,如下代码:
class Program
{
    static void Main(string[] args)
    {
           
        var xDoc = new XDocument(new XElement( "root",
            new XElement("dog",
                new XText("dog said black is a beautify color"),
                new XAttribute("color", "black")),
            new XElement("cat"),
            new XElement("pig", "pig is great")));

        //xDoc输出xml的encoding是系统默认编码,对于简体中文操作系统是gb2312
        //默认是缩进格式化的xml,而无须格式化设置
        xDoc.Save(Console.Out);

        Console.WriteLine();

        var query = from item in xDoc.Element( "root").Elements()
                    select new
                    {
                        TypeName    = item.Name,
                        Saying      = item.Value,
                        Color       = item.Attribute("color") == null?(string)null:item.Attribute("color").Value
                    };


        foreach (var item in query)
        {
            Console.WriteLine("{0} 's color is {1},{0} said {2}",item.TypeName,item.Color??"Unknown",item.Saying??"nothing");
        }

        Console.Read();
    }
}

3. Linq to xml简单的应用

应用需求: 读取博客园的rss,然后在页面上输出最新的10篇博客信息

实现要点: 通过XDocument的Load静态方法载入Xml,通过linq查询最新10条数据

代码如下:

<%@ Page Language="C#" AutoEventWireup="true" %>




    Linq to Xml 实例


    
  1. <%#Eval("PostTime") %>"><%#Eval("Title") %>

6.如何定义xsd文件

Xml Schema的用途

1.  定义一个Xml文档中都有什么元素

2.  定义一个Xml文档中都会有什么属性

3.  定义某个节点的都有什么样的子节点,可以有多少个子节点,子节点出现的顺序

4.  定义元素或者属性的数据类型

5.  定义元素或者属性的默认值或者固定值

Xml Schema的根元素:

表示数据类型等定义来自w3

targetNamespace="http://www.w3schools.com" 表示文档中要定义的元素来自什么命名空间

xmlns="http://www.w3schools.com"表示此文档的默认命名空间是什么

elementFormDefault="qualified"> 表示要求xml文档的每一个元素都要有命名空间指定

……定义主体部分……

如何定义一个简单元素

此处表示要定义一个元素

name=”color” 表示要定义元素的名称

type=”xs:string”  表示要定义元素的数据类型

default=”red” 表示定义元素的默认值

fixed=”red”/> 表示要定义元素的固定值,此元素只可以取“red”值

以上定义了一个简单元素,元素实例:red

如何定义一个属性

         name=”birthday” 表示要定义属性的名字

         type=”xs:date” 表示要定义属性的数据类型

         default=”2001-01-11” 表示要定义属性的默认值

         fixed=”2001-01-11” 表示要定义属性的固定值

         use=”required”/> 表示此属性是否是必须指定的,即如果不指定就不符合Schema,默认没有use=”required”属性表示属性可有可无

如何定义元素或者属性值的限制

1.最大值最小值限制

 大于等于0表示最小值但是不包括指定值

  小于等于120

2.枚举限制,指只能在指定的几个值中取值

         

  

    

    

    

  

3.模式(pattern)限制 ,指字符串的格式必须满足制定的匹配模式

例子

说明

  
    
  
 

表示只能在小写字母中取一个值

  
    
  
 
 

表示必须是三个大写字母

  
    
  
 
 

表示必须是三个字母,可以是大写或小写的

  
    
  
 

表示必须是xyz中的一个

  
    
  
 
 

表示数字的范围是0-99999

  
    
  
 
 

表示必须是0或者多个小写字符组成的序列

  
    
  
 
 

表示必须是多个字母。

  
    
  
 
 

表示是male或者female中的一个

  
    
  
 
 

表示必须是8个字母数字字符

4.字符串长度的限制

  

    

  

长度必须是8。

  

    

    

  

表示长度在5-8之间

6. 对于空白字符的限制

示例

说明

  
    
  
 

保留原样,表示xml处理器不会移除或者替换任何空白字符

  
    
  
 
 

指回车,换行,Tab都会被替换成空格处理

  
    
  
 
 

去掉多于一个空格,和html中处理方式相同

 

如何定义复杂类型

复杂类型是指定义元素中包含属性或者子元素的类型

1. 定义只包含子元素的复杂类型

  

    

      

      

    

  

2. 定义只包含属性的复杂类型

  

3. 定义只包含内容的复杂类型

  

    

      

    

  

4. 定义包含内容和子元素混合的复杂类型

   mixed="true">

    

      

      

      

    

  

以上定义对应的Xml

Dear Mr.John Smith.

Your order 1032

will be shipped on 2001-07-13.

5. 定义包含属性和子元素的复杂类型

 

使用指示器

在Xsd中的指示器包括

1. 顺序指示器

1) All

指示子元素可以以任何顺序出现,并且每一个元素都必须出现一次

  

    

      

      

    

  

2) Choice

指示子元素中可以出现一个或者另一个

  

    

      

      

    

  

3) Sequence

指示子元素必须按照顺序出现

  

    

      

      

    

  

2. 出现次数指示器minOccurs,maxOccurs

  

    

      

      

      maxOccurs="10" minOccurs="0"/>

    

  

3. 组指示器(group Indicators)

用来定义相关的一组元素

  

    

    

    

  

  

    

    

  

   

用来定义一组相关的属性

  

  

  

  

    

  

Any关键字

表示可以有任意元素

  

    

      

      

      

    

  

anyAttribute关键字

  

    

      

      

    

    

  

substitutionGroup关键字

表示某一个元素和另一个替代元素定义相同

  

    

  


文中的例子都来自w3school.



7.XmlSerializer对象的Xml序列化和反序列化

这篇随笔对应的.Net命名空间是System.Xml.Serialization;文中的示例代码需要引用这个命名空间。
为什么要做序列化和反序列化?
.Net程序执行时,对象都驻留在内存中;内存中的对象如果需要传递给其他系统使用;或者在关机时需要保存下来以便下次再次启动程序使用就需要序列化和反序列化。
范围: 本文只介绍xml序列化,其实序列化可以是二进制的序列化,也可以是其他格式的序列化。
看一段最简单的Xml序列化代码
class Program
{
    static void Main(string[] args)
    {
        int i = 10;
        //声明Xml序列化对象实例serializer
        XmlSerializer serializer = new XmlSerializer(typeof(int));
        //执行序列化并将序列化结果输出到控制台
        serializer.Serialize(Console.Out, i);
        Console.Read();
    }
}

上面代码对int i进行了序列化,并将序列化的结果输出到了控制台,输出结果如下

10
可以将上述序列化的xml进行反序列化,如下代码
static void Main(string[] args)
{
    using (StringReader rdr = new StringReader(@"
10"))
    {
        //声明序列化对象实例serializer 
        XmlSerializer serializer = new XmlSerializer(typeof(int));
        //反序列化,并将反序列化结果值赋给变量i
        int i = (int)serializer.Deserialize(rdr);
        //输出反序列化结果
        Console.WriteLine("i = " + i);
        Console.Read();
    }
}

以上代码用最简单的方式说明了xml序列化和反序列化的过程,.Net系统类库为我们做了大量的工作,序列化和反序列化都非常简单。但是在现实中业务需求往往比较复杂,不可能只简单的序列化一个int变量,显示中我们需要对复杂类型进行可控制的序列化。

自定义对象的Xml序列化:

System.Xml.Serialization命名空间中有一系列的特性类,用来控制复杂类型序列化的控制。例如XmlElementAttribute、XmlAttributeAttribute、XmlArrayAttribute、XmlArrayItemAttribute、XmlRootAttribute等等。

看一个小例子,有一个自定义类Cat,Cat类有三个属性分别为Color,Saying,Speed。

namespace UseXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明一个猫咪对象
            var c = new Cat { Color = "White", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat" };

            //序列化这个对象
            XmlSerializer serializer = new XmlSerializer(typeof(Cat));

            //将对象序列化输出到控制台
            serializer.Serialize(Console.Out, c);

            Console.Read();
        }
    }

    [XmlRoot("cat")]
    public class Cat
    {
        //定义Color属性的序列化为cat节点的属性
        [XmlAttribute("color")]
        public string Color { get; set; }

        //要求不序列化Speed属性
        [XmlIgnore]
        public int Speed { get; set; }

        //设置Saying属性序列化为Xml子元素
        [XmlElement("saying")]
        public string Saying { get; set; }
    }
}

可以使用XmlElement指定属性序列化为子节点(默认情况会序列化为子节点);或者使用XmlAttribute特性制定属性序列化为Xml节点的属性;还可以通过XmlIgnore特性修饰要求序列化程序不序列化修饰属性。

对象数组的Xml序列化:

数组的Xml序列化需要使用XmlArrayAttribute和XmlArrayItemAttribute;XmlArrayAttribute指定数组元素的Xml节点名,XmlArrayItemAttribute指定数组元素的Xml节点名。

如下代码示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace UseXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明一个猫咪对象
            var cWhite = new Cat { Color = "White", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat" };
            var cBlack = new Cat { Color = "Black", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat" };

            CatCollection cc = new CatCollection { Cats = new Cat[] { cWhite,cBlack} };

            //序列化这个对象
            XmlSerializer serializer = new XmlSerializer(typeof(CatCollection));

            //将对象序列化输出到控制台
            serializer.Serialize(Console.Out, cc);

            Console.Read();
        }
    }

    [XmlRoot("cats")]
    public class CatCollection
    {
        [XmlArray("items"),XmlArrayItem("item")]
        public Cat[] Cats { get; set; }
    }

    [XmlRoot("cat")]
    public class Cat
    {
        //定义Color属性的序列化为cat节点的属性
        [XmlAttribute("color")]
        public string Color { get; set; }

        //要求不序列化Speed属性
        [XmlIgnore]
        public int Speed { get; set; }

        //设置Saying属性序列化为Xml子元素
        [XmlElement("saying")]
        public string Saying { get; set; }
    }
}
以上代码将输出:


  
    
      White or black,  so long as the cat can catch mice,  it is a good
cat
    
    
      White or black,  so long as the cat can catch mice,  it is a good
cat
    
  

XmlSerializer内存泄漏问题:

多谢chenlulouis,仔细看了下msdn,确实存在泄漏的情况,msdn说明如下:

动态生成的程序集 

为了提高性能,XML 序列化基础结构将动态生成程序集,以序列化和反序列化指定类型。此基础结构将查找并重复使用这些程序集。此行为仅在使用以下构造函数时发生: 

XmlSerializer(Type) 
XmlSerializer.XmlSerializer(Type, String) 

如果使用任何其他构造函数,则会生成同一程序集的多个版本,且绝不会被卸载,这将导致内存泄漏和性能降低。最简单的解决方案是使用先前提到的两个构造函数的其中一个。否则,必须在 Hashtable 中缓存程序集,如以下示例中所示。

也就是说我们在使用XmlSerializer序列化,初始化XmlSerializer对象时最好使用下面两个构造函数否则会引起内存泄漏。
XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)

8.XSLT语法 在.net使用XSLT转换xml文档示例

XSL即可扩展的样式表文件。 可以格式化xml的显示,也可以将xml转换成需要的另一种格式。

学习XSL必须熟悉XPath。XSL和XPath一样简单强大,容易学习。

1. XSL既然可以格式化xml的显示样式,我们先来看如何在xml中引用xsl文件

如下代码示例:

只需在xml文件的文档声明后面添加即可

2. XSL的格式

XSL也是一个标准的xml文件,它以xml文档声明开始,根元素必须是xsl:styleshee,同时根元素必须有version属性指定xsl的版本,和xmlns:xsl=” http://www.w3.org/1999/XSL/Transform”指定xsl命名空间,如下示例

3. Xsl要点 如下示例xml




  
    100
    this is a blue pig
  
  
    80
    this is a red cat
  
  
    80
    this is a green dog
  
  
    80
    this is a green cat
  


  
    100
    this is a blue dog
  
  
    80
    this is a red dog
  

1) xsl:template定义匹配节点的转换模板,属性match=”xpath expression”用来定义模板匹配的元素

如下定义匹配根节点的模板

2) xsl:for-each循环显示select=”xpath expression”选择节点的转换 (类似编程语言中的foreach语句),

如下示例,选择了pets下面的子元素,并循环显示子元素的几点名字:

3) xsl:if 元素条件显示节点(类似编程语言中的if语句)注意小于号大于号要分别用<和>替代

its weight is less than 10 km

4) xsl:choose 多分支条件显示 (类似编程语言中的switch语句)

 

this is a pig

 

  this is not a pig

5) xsl:value-of 显示选择节点或者属性的值

选择子节点price

选择属性weight

6) xsl:attribute 构造xml节点的属性

用来向节点添加属性,例如:

将输出

7) xsl:apply-templates 应用模板

 如果xml文件结构比较复杂,可以定义多个template,然后使用标签应用模板,xsl:apply-templates 可以指定属性select=”xpath”来选择应用的模板,或者不指定select表示选择当前节点的模板。

 请看下面示例xslt文件pets-templates.xsl

完整的示例xsl文件:pets.xsl


  
    
      
        
        lovely pets
        
      
      
        

lovely pets

  • http://estar-tv.com/images/comprofiler/gallery/dog.gif http://www.icosky.com/icon/thumbnails/Animal/Farm/Pig%20Icon.jpg http://farm1.static.flickr.com/14/buddyicons/[email protected]?1143660418 Courier said: "" weight:

    its weight is less than 10 km


完整示例文件 pets-templates.xsl


  
    
      
        
        lovely pets
        
      
      
        

lovely pets

  • http://estar-tv.com/images/comprofiler/gallery/dog.gif http://www.icosky.com/icon/thumbnails/Animal/Farm/Pig%20Icon.jpg http://farm1.static.flickr.com/14/buddyicons/[email protected]?1143660418 Courier said: "" weight:

    its weight is less than 10 km

完整示例文件 pets-templates.xsl: lovely pets

lovely pets

  • http://estar-tv.com/images/comprofiler/gallery/dog.gif Courier dog said: "" weight:

    its weight is less than 10 km

  • http://www.icosky.com/icon/thumbnails/Animal/Farm/Pig%20Icon.jpg Courier pig said: "" weight:

    its weight is less than 10 km

  • http://farm1.static.flickr.com/14/buddyicons/[email protected]?1143660418 Courier cat said: "" weight:

    its weight is less than 10 km


  • 在c#.net中使用XslCompiledTransform转换xml文档,XslTransform也可以使用,但是这个类已经被微软标记为过时,最好不要再用了,如下代码示例:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Xml;
    
    namespace UseXslt
    {
        class Program
        {
            static void Main(string[] args)
            {
                //声明XslTransform类实例
                System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
    
                string xsltFile = @"X:\about.net\System.Xml\example\pets.xsl";
                using (StreamReader rdr = new StreamReader(xsltFile))
                {
                    using (XmlReader xmlRdr = XmlReader.Create(rdr))
                    {
                        //载入xsl文件
                        trans.Load(xmlRdr);
                    }
                }
                string inputFile = @"X:\about.net\System.Xml\example\pets.xml";
                string outputFile = @"X:\about.net\System.Xml\example\pets-out.htm";
                //转化源文件输出到输出文件outputFile
                trans.Transform(inputFile, outputFile);
            }
        }
    }

    有一点需要注意,使用XslCompiledTransform转换出来的文件,是一个html格式的,这个类会自动在html的head标签中添加一个未关闭的meta标签 ;微软帮我们想的太多了。

    Xslt还可以指定参数,定义变量,有关这些方面请查看相关文档。






    你可能感兴趣的:(XML)