• 学习笔记 XML、生成Excel、XML加密解密


    今天本来想整理下ASP.NET MVC, 做个增删改查的Demo. 可是, 又不想去动数据库, 于是想到了XML. 可是, 突然发现对XML的认识和了解还不够系统, 无奈先整理下XML吧! %>_<%!!!!!!!!!!!!!!!!!!!

    一、 XML

    XML(eXtensible Markup Language, 扩展标记语言), 是W3C(WWW Confederation, 万维网联盟)认可的文档标记标准. XML是用来描述数据的一种格式, 这种格式使用简单, 可以用来描述无穷无尽的类型的数据.

    关于XML的历史, XML源自IBM的SGML(Standard Generalized Markup Language, 标准通用标记语言), …… 如是云云.

    XML默认的版本号为1.0, 默认编码方式为UTF-8. 这在XML文件的指令中给出, 如:

    <?xml version=”1.0” encoding=”UTF-8”?>. 关于XML的基础知识, 可以看随后贴出的Xml Schema示例.

    XML Schema是用来规范XML格式的, 也就是说XML是一种描述数据的格式, 而Xml Schema是规范并检查Xml格式的. 通俗点说就是: 我们用XML描述了一堆数据, 但是不同的人有不同的思考角度, 如是乎就有了很多种不同的数据描述, 那么程序是固定的, 我们可以用XML Schema来约定只有符合Schema约定的数据描述XML文件才是可用的. 用来约定XML的有两种, 一种是XML Schema, 一种是DTD(Document Type Definition, 文档类型定义), 后者在HTML领域用的多, 在XML领域还是Schema吧.

    我们如何来获得XML中的数据呢? 使用XPath, XPath相当于数据库中的Select语句, 可以看做是XML中的Select语句.

    关于XPath的基础知识, 看接下的Xml Schema的示例.

    值得一提的是, XSL(eXtensible Stylesheet Language, 扩展样式表语言)是一种脚本语言, 可以用来将XML文档转换成其他的文档格式, 如html. 这种转化过程叫做XSLT(XSL – Transformation, xsl转换), 这个脚本语言是一种专门的语言, 应用的话也不是没有, 但是不多, 等需要的时候在看吧.

    Xml Schema示例:

    //XMLOperation.xml

    代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- XML基础知识概述:

    1. 字符编码:
    ASCII码常见字符: Tab -> 9、回车换行(\r\n) -> 13 10、空格 -> 32、0 -> 48、A -> 65、a -> 97
    GB2312采用双字节存储汉字: 首字节在0-127表示英文, >127将联合下一个字节表示汉字.
    文件头: Unicode(FF FE)、Unicode-big-endian(FE FF)、UTF-8(EF BB BF). 计算机内部采用Unicode编码, 传输和保存时采用UTF-8编码, 若没有文件头, 则默认采用UTF-8编码.
    字符编码的类Encoding的三个重要方法: GetEncoding()、GetBytes()和GetChars()

    2. XML仅仅是描述数据的格式, 而XML Schema是用来定义XML的规范, 即检查XML文件是否符合Schema的规定.
    注意事项: XML区分大小写、属性需用引号括起来且不区分单双引号.
    XML的元素(8种):
    a. XML的定义: 如: <?xml version="1.0" encoding="GB2312"?>
    b. 元素: <author>张三</author>, 空元素可以简写为</author>
    c. 属性: <book code="1234"></book>, code为属性, 多个属性一空格分隔.
    d. 文本内容: 如上边的张三. 可以使用&#十进制;和&#x十六进制;表示字符编码表上的对应字符, &#1968;别忘记分号.
    e. 实体参考: 类似于特殊符号的转义. 如: (&lt;、&gt;、&amp;、&quot;、&apos;)分别表示<、>、&、"、', 分号不能省.对应英文为: less than、greater than、ampersand、quotation、apostrophe. 例如: &amp;表示为&amp;amp;
    f. 注释: 本段最外层即为注释
    g. CDATA: 即字符数据Character Data, 也就是不需要XML解析的内容, 如: <![CDATA[...内容...]]>
    h. PI处理指令: 如<?指令名 指令内容?>, 如第一行, xml是指令名, 后便的为指令值, 且可以有多个值. 如:<?xml-stylesheet type="text/xsl" href="book.xslt"?>

    3. Xml Schema:
    示例: <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="aspnet" targetNamespace="aspnet" elementFormDefault="qualified" attributeFormDefault="unqualified"></xs:schema>
    a. xs:schema表示xs前缀(prefix)代表的命名空间下的schema根元素; xmlns:xs="..."表示xml namespace(xmlns)命名空间, xs是命名空间的代号, 它指代=号后边的内容, 此外还可以为schema中的元素及属性设置(attribute)不同的命名空间, 这样在不同的命名空间中, 可以使用相同的元素名. 例如: 上例中的xmlns:ns1="..."中ns1代表=号后内容的, targetNamespace表示目标命名空间, 即定义的命名空间. elementFormDefault="qualified"表示元素默认需要写出命名空间如: xs、ns1, attributeFormDefault="unqualified"表示属性可以不写命名空间, 默认与元素的命名空间相同.
    b. XmlSchema只有两种数据类型: 简单类型(不包含子元素和属性), 复杂类型(包含子元素或属性). 若是复杂类型必须用<complexType>标记, 若复杂类型包含子元素则必须用<sequence>表示子元素的顺序.
    c. type属性用来表示简单元素的类型: xs:string、xs:integer、xd:boolean, 注意XML没有char类型.
    d. 通过ref可以直接将元素指向另一个模块, 从而简化schema的复杂度.
    e. 元素属性(attribute)的定义需要先定义子元素(与<sequence>并列且在<squence>下面), 然后在定义元素的属性. 可用空的<sequence></sequence>表示空元素.
    f. 可以使用<choise>定义从n个子元素中选择1个元素.
    g. 可以用minOccurs和maxOccurs来定义子元素的数量范围(可为0), 可以使用default设置默认值.
    h. 可以使用<enumeration value="...">列举可选的值, 使用<minInclusive value="...">和<maxInclusive value="...">确定取值范围.
    i: 使用use表示是否为必须存在的属性, required必须、optional可选、prohibited无属性的值
    j: 可以采用<attributeGroup>重新改写复杂元素的属性

    4. XPath: 用来获取XML中的元素
    路径: / 根、 绝度路径(从/开始的路径)、相对路径(不从/开始的短路径)、圆点表示当前节点、两个圆点表示上一个节点
    相对路径: 找到上级元素后, 点击"I"型按钮设置相对路径, 之后就可以直接找子元素了
    元素名: 如: /configuration/system.web/httpHandlers/add, add表示所有的匹配元素
    属性名: 用@属性名获取属性值, 如: @validate
    函数: 通过函数取得节点内容, 常见函数: text()、comment()、processing-instruction(), 如: /configuration/appSettings/text()和/configuration/system.web/httpHandlers/comment()
    处理节点的函数: 当前节点序号position()、当前上下文节点数last()、参数的节点数count()、返回具有指定id的节点集合id()、第一个节点的本地名local-name()、第一个节点的名称空间namespace-uri()、第一个节点的带前缀的名称name
    字符串函数: string()、start-with()、contains()、第一次匹配之前的串substring-before()、第一次匹配之后的串substring-after()、substring()、string-length()、格式化元素中的空白normalize-space()
    //和|: //表示从所有的后代中匹配, |用于合并匹配的结果, 如: //configuration/system.web/httpHandlers/add/(@verb | @validate
    通配符: *(匹配任意节点, 不含属性、文本、注释及处理指令)、node()(匹配所有的节点, 含属性、文本、注释等)、@*(匹配所有的属性节点), 例如: 通配符: *(匹配任意节点, 不含属性、文本、注释及处理指令)、node()(匹配所有的节点, 含属性、文本、注释等)、@*(匹配所有的属性节点), 例如: //configuration/system.web/httpHandlers/add/@*
    [@属性名="..."]: 类似于Sql中的where, 如: /configuration/system.web/httpHandlers/add [@verb="GET,POST"]/@validate, 找到verb=get,post的add元素的validate值

    ###############################示例如下##################################
    -->
    <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <appSettings> web.config不好找简单类型, 就暂且拿这个当个简单类型吧! </appSettings>
    <connectionStrings>
    <add name="calendar" connectionString="server=192.168.0.67\.;database=calendar;integrated security=true;"/>
    </connectionStrings>
    <system.codedom>
    <compilers>
    <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <providerOption name="CompilerVersion" value="v3.5"/>
    <providerOption name="WarnAsError" value="false"/>
    </compiler>
    <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <providerOption name="CompilerVersion" value="v3.5"/>
    <providerOption name="OptionInfer" value="true"/>
    <providerOption name="WarnAsError" value="false"/>
    </compiler>
    </compilers>
    </system.codedom>
    <system.web>
    <httpHandlers>
    <cellphone>1398-371-9899</cellphone>
    <!--新加的简单类型! -->
    <salary amount="4000"/>
    <remove verb="*" path="*.asmx"/>
    <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add verb="GET,POST" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
    </httpHandlers>
    </system.web>
    </configuration>

    //XMLOperation.xsd

    代码
    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xs:element name="configuration">
    <!--复杂类型一定有子元素或者属性, 只要是复杂类型, 写个名就往里分-->
    <xs:complexType>
    <!--先写子元素, 后写属性, 且子元素需要说明其顺序-->
    <xs:sequence>
    <!--简单类型无子元素也无属性, 不再往里分了, 指定数据类型结束-->
    <xs:element name="appSettings" type="xs:string" maxOccurs="1" minOccurs="0"/>
    <xs:element name="connectionStrings" maxOccurs="1" minOccurs="0"><!--原始写法-->
    <xs:complexType>
    <xs:sequence>
    <xs:element name="add">
    <xs:complexType>
    <!--只有属性, 没有子元素-->
    <xs:attribute name="name" type="xs:string" use="required"/>
    <xs:attribute name="connectionString" type="xs:string" use="required"/>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    <xs:element name="system.codedom"><!--原始写法-->
    <xs:complexType>
    <xs:sequence>
    <xs:element name="compilers">
    <xs:complexType>
    <xs:sequence>
    <xs:element name="compiler" minOccurs="1" maxOccurs="unbounded">
    <xs:complexType>
    <xs:sequence>
    <xs:element name="providerOption" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
    <xs:attribute name="name" type="xs:string" use="required"/>
    <xs:attribute name="value" type="xs:string" use="required"/>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    <xs:attribute name="language" type="xs:string" use="required"/>
    <xs:attribute name="extension" type="xs:string" use="required"/>
    <xs:attribute name="warningLevel" type="xs:integer" use="required"/>
    <xs:attribute name="type" type="xs:string" use="required"/>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    <xs:element name="system.web"><!--通过ref简化schema-->
    <xs:complexType>
    <xs:sequence>
    <xs:element ref="httpHandlers" maxOccurs="1"/>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    <!--sequence之后写属性, 属性不再往里分了, 制定数据类型结束-->
    </xs:complexType>
    </xs:element >

    <xs:element name="httpHandlers">
    <xs:complexType>
    <xs:sequence>
    <xs:choice><!--使用choice从n个子元素中选择一个-->
    <xs:element name="cellphone" type="customizeType"/><!--使用自定义简单类型, 使用正则表达式-->
    <xs:element name="email" type="xs:string"/>
    <xs:element name="telphone" type="xs:string"/>
    </xs:choice>
    <xs:element name="salary"><!--使用minInclusive和maxInclusive限定范围-->
    <xs:complexType>
    <xs:attribute name="amount" type="amountType"/>
    </xs:complexType>
    </xs:element>
    <xs:element name="remove" minOccurs="0" maxOccurs="1"><!--使用attributeGroup属性组-->
    <xs:complexType>
    <xs:attributeGroup ref="removeAttributes"></xs:attributeGroup>
    </xs:complexType>
    </xs:element>
    <xs:element ref="add" minOccurs="1" maxOccurs="unbounded"/><!--使用ref简化复杂度-->
    </xs:sequence>
    </xs:complexType>
    </xs:element>

    <xs:element name="add"><!--使用ref简化复杂度, 使用enumeration获得允许的属性值-->
    <xs:complexType>
    <xs:attribute name="verb" type="enumVerbType" use="required"/>
    <xs:attribute name="path" type="xs:string" use="required"/>
    <xs:attribute name="validate" type="xs:boolean" use="optional"/>
    <xs:attribute name="type" type="xs:string" use="required"/>
    </xs:complexType>
    </xs:element>

    <xs:attributeGroup name="removeAttributes"><!--使用attributeGroup属性组, 使用default默认值-->
    <xs:attribute name="verb" type="xs:string" use="optional" default="*"/>
    <xs:attribute name="path" type="xs:string" use="required"/>
    </xs:attributeGroup>

    <xs:simpleType name="customizeType"><!--使用正则表达式-->
    <xs:restriction base="xs:string">
    <xs:pattern value="\d{4}-\d{3}-\d{4}"/>
    </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="enumVerbType"><!--使用enumeration获得允许的属性值-->
    <xs:restriction base="xs:string">
    <xs:enumeration value="*"/>
    <xs:enumeration value="GET"/>
    <xs:enumeration value="POST"/>
    <xs:enumeration value="GET,POST"/>
    </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="amountType"><!--使用minInclusive和maxInclusive限定范围-->
    <xs:restriction base="xs:integer">
    <xs:minInclusive value="3000"/>
    <xs:maxInclusive value="7000"/>
    </xs:restriction>
    </xs:simpleType>

    </xs:schema>

    接下来, 才是我们程序员最关心的事情, 如何在程序中读写XML文档.

    为了能够在开发过程中使用XML, W3C指定了DOM规范, 即Document Object Model, 文档对象模型. DOM可以看做是XML或HTML文件在内存中的表示, 它是一个树形结构, document节点永远是这棵树的根节点. 在.NET中, System.Xml命名空间下定义了处理XML的类型. XmlNode为所有节点的基类, 其他节点类型直接或间接派生自XmlNode, 如下图:

    如上图所示, 我们有3中方式操作XML文档, 3中方式各有优缺点.

    建议的方式: 使用XPathDocument进行查询操作, 使用XML流进行一次性的创建和读取操作, 使用XPath进行修改操作.

    详见示例:

    读取的xml文件和xsd文件, 就是上例中的XMLOperation.xml和XMLOperation.xsd文件.

    //Program.cs

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

    namespace XMLDemo
    {
    class Program
    {
    staticvoid Main(string[] args)
    {
    #region 使用文本对象模型DOM(Document Object Model)和XPath操作XML, 缺点: 全部读到内存中, 消耗内存且较慢;
    /*
    //1. 创建读写XML的document对象
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

    //2. 读取XML
    doc.Load("XMLOperation.xml");

    //3. 处理
    #region 使用Node获取信息, 数节点方式
    Console.WriteLine("---------------XML节点文本-----------------");
    System.Xml.XmlElement root = doc.DocumentElement; //获取根元素
    System.Xml.XmlText text = root.ChildNodes[3].ChildNodes[0].ChildNodes[0].ChildNodes[0] as System.Xml.XmlText; //text内容被看做是单独的子节点
    Console.WriteLine(text.Value);
    #endregion

    #region 使用XPath获取信息
    Console.WriteLine("---------------XPath获得文本及属性值-----------------");
    string xpath = "/configuration/system.web/httpHandlers/add"; //反斜杠不用转义, 通过XMLSpy获得xpath
    System.Xml.XmlNodeList nodes = doc.SelectNodes(xpath);
    foreach (System.Xml.XmlNode node in nodes)
    {
    Console.WriteLine(string.Format("add元素name={0}, validate={1}", node.Attributes["verb"].Value, node.Attributes["validate"].Value));
    }
    Console.WriteLine("------XPath获得文本, 文本内容当作节点处理------");
    xpath = "/configuration/system.web/httpHandlers/cellphone";
    text = doc.SelectSingleNode(xpath).ChildNodes[0] as System.Xml.XmlText; //文本内容当作一个节点
    Console.WriteLine(text.Value);
    Console.WriteLine("------------修改dom对象--------------");
    text.Value = "xxxx";
    Console.WriteLine(text.Value);
    Console.WriteLine("------------创建dom元素对象--------------");
    //创建一个节点
    System.Xml.XmlElement newelem = doc.CreateElement("name");
    System.Xml.XmlText newelemtext = doc.CreateTextNode("这里写名字! "); //要插入的文本节点内容
    newelem.AppendChild(newelemtext);
    newelem.SetAttribute("id", "001"); //直接通过SetAttribute设置属性
    //获取要插入的节点
    System.Xml.XmlElement oldelem = doc.SelectSingleNode("/configuration/system.web/httpHandlers") as System.Xml.XmlElement;
    oldelem.AppendChild(newelem);
    Console.WriteLine("插入完毕! ");
    Console.WriteLine("------------删除dom对象--------------");
    //查找要删除的节点, 并获得其父节点
    System.Xml.XmlNode delNode = doc.SelectSingleNode("/configuration/system.web/httpHandlers/salary");
    System.Xml.XmlNode parenNode = delNode.ParentNode;
    parenNode.RemoveChild(delNode);
    Console.WriteLine("删除完毕! ");
    #endregion

    //4. 写入XML
    Console.WriteLine("----------------XML内容--------------------");
    doc.Save(Console.Out); //输出到控制台

    */
    #endregion

    #region 使用XML流处理, 每次只处理一个节点, 速度快, 但缺点是: 不支持结构化查询, 适合从头到尾一次性处理
    /*
    System.IO.Stream fs = new System.IO.FileStream("XMLOperation.xsd", System.IO.FileMode.Open, System.IO.FileAccess.Read); //读的是xsd

    //设置读取Xml时的Schema, 确保数据能正确读取(Schema)
    System.Xml.Schema.XmlSchema schema = System.Xml.Schema.XmlSchema.Read(fs, new System.Xml.Schema.ValidationEventHandler(dealSchemaValidation));
    Console.WriteLine("-------------Schema读取完毕---------------");

    //配置Xml读取设置, 用来验证xml(xml)
    System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings();
    settings.Schemas.Add(schema); //添加Schema到Schemas集合, 同一个XML可由多个schema验证
    settings.ValidationType = System.Xml.ValidationType.Schema; //设置验证方式
    settings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(dealSchemaValidation); //设置验证事件处理器
    //使用XmlReader读取XML, 验证过程在读取的时候执行. 也可以单独用XmlReader配合空While读一遍Xml文件进行验证
    using (System.Xml.XmlReader xmlreader = System.Xml.XmlReader.Create("XMLOperation.xml", settings)) //通过XmlReader的工厂方法获得XmlReader流适合读取
    {
    Console.WriteLine("输出xml中的所有属性: ");
    while (xmlreader.Read())
    {
    if (xmlreader.NodeType == System.Xml.XmlNodeType.Element)
    {
    if (xmlreader.HasAttributes)
    {
    for (int i = 0; i < xmlreader.AttributeCount; i++)
    {
    xmlreader.MoveToAttribute(i); //移动到属性的位置
    Console.WriteLine("属性名:{0}, 类型:{1}, 属性值:{2}", xmlreader.Name, xmlreader.ValueType, xmlreader.Value); //xmlreader.LocalName不带命名空间
    }
    }
    //Console.WriteLine("InnerXml: " + xmlreader.ReadInnerXml());
    //Console.WriteLine("OuterXml: " + xmlreader.ReadOuterXml());
    //读取cellphone元素
    //if (xmlreader.ReadToFollowing("cellphone"))
    //{
    // Console.WriteLine(xmlreader.ReadElementString("cellphone")); //读取cellphone元素的文本
    //}
    }
    }
    Console.WriteLine("验证完毕! ");
    }
    //使用xml流输出字符
    using (System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create("Output.xml"))
    {
    xmlwriter.WriteStartDocument();
    xmlwriter.WriteStartElement("human"); //</humen>
    xmlwriter.WriteStartElement("man"); //子元素
    //写元素属性
    xmlwriter.WriteAttributeString("name", "father"); //属性
    xmlwriter.WriteString("Mike"); //文本区
    xmlwriter.WriteEndElement();

    xmlwriter.WriteElementString("women", "jean"); //<women>jean</women>

    xmlwriter.WriteStartElement("children");
    xmlwriter.WriteAttributeString("name", "kiddy");
    xmlwriter.WriteString("nickey kiddy"); //文本区
    xmlwriter.WriteEndElement();

    xmlwriter.WriteEndElement();
    }
    */
    #endregion

    #region 使用优化的XPath--XPathDocument类, 速度快, 也支持结构化的查询方式. 缺点: 只能读不能写
    //1.创建XPathDocument对象
    System.Xml.XPath.XPathDocument xpdoc =new System.Xml.XPath.XPathDocument("XMLOperation.xml");

    //2.通过导航器进行查找
    System.Xml.XPath.XPathNavigator xpnav = xpdoc.CreateNavigator();

    /*#######################################################################################
    * 带有命名空间的XML
    //定义命名空间管理器
    System.Xml.XmlNamespaceManager xnm = new System.Xml.XmlNamespaceManager(xpnav.NameTable);
    xnm.AddNamespace("xsi","
    http://www.w3.org/2001/XMLSchema-instance");
    string nmxpath = "/xsi:configuration/xsi:system.web/xsi:httpHandlers/xsi:add/@type";
    System.Xml.XPath.XPathExpression nmxpe = System.Xml.XPath.XPathExpression.Compile(nmxpath);
    nmxpe.SetContext(xnm); //在XPath表达式上设置当前的命名空间管理器
    System.Xml.XPath.XPathNavigator nmresultNav = xpnav.SelectSingleNode(nmxpe);
    Console.WriteLine(nmresultNav.Value);
    *#######################################################################################
    */

    //3.经过编译的XPath
    string xpath ="/configuration/system.web/httpHandlers/cellphone";
    System.Xml.XPath.XPathExpression xpe
    = System.Xml.XPath.XPathExpression.Compile(xpath);

    //4.使用导航器的Select迭代器进行查找, 查找的结果还是导航器
    System.Xml.XPath.XPathNavigator resultNav = xpnav.SelectSingleNode(xpe);
    Console.WriteLine(
    "----------XPathDocument的查询单个结果----------");
    Console.WriteLine(resultNav.Value);
    //查找多个结果
    Console.WriteLine("----------XPathDocument的查询多个结果----------");
    xpath
    ="/configuration/system.web/httpHandlers/add/@type"; //查找add元素的type属性内容
    xpe = System.Xml.XPath.XPathExpression.Compile(xpath);
    System.Xml.XPath.XPathNodeIterator xpniter
    = xpnav.Select(xpe);
    foreach (System.Xml.XPath.XPathNavigator xpn in xpniter)
    {
    Console.WriteLine(xpn.Value);
    }

    #endregion
    }

    staticvoid dealSchemaValidation(object sender, System.Xml.Schema.ValidationEventArgs e)
    {
    Console.WriteLine(
    "验证过程出错, 错误等级:{0}, 错误详情:{1}", e.Severity, e.Message);
    }
    }
    }

    二、 生成Excel

    数据库对于一般的公司职员来说, 似乎不太容易上手. 但他们是对Excel文件, 确是”情有独钟”. 那么, 我们程序员处理完的各项数据最好能够保存为一般职员擅长的Excel文件. 但是, .NET并没有给我们提供创建Excel的方式, 但是我们可以通过xml来生成Excel文件, excel文件也可以另存为xml文件.

    下面的例子, 用来演示xml和excel交互处理情况.

    //处理带有命名空间的XML文件的元素和属性, ---生成Excel的xml文档; 以及使用ExcelXmlWriter生成Excel文档.

    //Program.cs

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace XmlAndExcelDemo
    {
    class Program
    {
    //元素的命名空间经常使用, 这里使用串存放命名空间串, 不加冒号表示默认命名空间
    privateconststring o ="urn:schemas-microsoft-com:office:office";
    privateconststring x ="urn:schemas-microsoft-com:office:excel";
    privateconststring ss="urn:schemas-microsoft-com:office:spreadsheet";//ss就是默认命名空间
    privateconststring html ="http://www.w3.org/TR/REC-html40";

    staticvoid Main(string[] args)
    {
    #region 处理带有命名空间的XML, --- 生成Excel使用的xml文档
    /*
    //Dom(Document Object Model)通用性更强, 这里采用Dom树(文件对象模型)方式生成XML文件
    //创建Dom对象的实例, 即根结点
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

    //由于XmlVersion那行由系统生成, 因此创建的第一个元素, 即为范本中的第二行
    //创建指令对象, xml version标记会自动生成, 不需要书写
    //System.Xml.XmlProcessingInstruction xmlpi = new System.Xml.XmlProcessingInstruction();//---X, 指令须通过XmlDocument对象创建(Create方法)
    System.Xml.XmlProcessingInstruction xmlpi = doc.CreateProcessingInstruction("mso-application", "progid='Excel.Sheet'");
    doc.AppendChild(xmlpi);

    //创建根元素Workbook(第一个Element元素, 这里指的不是根, 根是document)
    System.Xml.XmlElement workbook = doc.CreateElement("Workbook",ss);//dom树中, 元素的创建都通过document进行, 因为各元素的命名空间经常使用, 可以作为串放在外边
    workbook.SetAttribute("xmlns:o",o);
    workbook.SetAttribute("xmlns:x",x);
    workbook.SetAttribute("xmlns:ss",ss);
    workbook.SetAttribute("xmlns:html",html);
    doc.AppendChild(workbook);


    //创建Styles元素-----<Styles块>
    System.Xml.XmlElement styles = doc.CreateElement("Styles",ss);
    workbook.AppendChild(styles);

    //创建style元素
    System.Xml.XmlElement style = doc.CreateElement("Style",ss);
    style.SetAttribute("ID",ss,"Default");
    style.SetAttribute("Name",ss,"Normal");
    styles.AppendChild(style);

    //创建Alignment元素
    System.Xml.XmlElement alignment = doc.CreateElement("Alignment",ss);
    alignment.SetAttribute("Vertical",ss,"Center");
    style.AppendChild(alignment);

    //创建Font元素
    System.Xml.XmlElement font = doc.CreateElement("Font",ss);
    font.SetAttribute("FontName",ss,"宋体");
    font.SetAttribute("CharSet",x,"134");
    font.SetAttribute("Size",ss,"12");
    style.AppendChild(font);


    //创建WorkSheet-----<WorkSheet块>
    System.Xml.XmlElement worksheet = doc.CreateElement("Worksheet",ss);
    worksheet.SetAttribute("Name",ss,"Sheet1");
    workbook.AppendChild(worksheet);

    //创建table元素
    System.Xml.XmlElement table = doc.CreateElement("Table",ss);
    table.SetAttribute("ExpandedColumnCount", ss, "1");
    table.SetAttribute("ExpandedRowCount", ss, "5");
    table.SetAttribute("FullColumns", x, "1");
    table.SetAttribute("FullRows",x,"1");
    table.SetAttribute("DefaultColumnWidth", ss, "54");
    table.SetAttribute("DefaultRowHeight", ss, "14.25");
    worksheet.AppendChild(table);

    //创建Row元素, 通过for循环添加row元素
    for (int i = 0; i < 5; i++)
    {
    System.Xml.XmlElement row = doc.CreateElement("Row", ss);
    table.AppendChild(row);
    //创建cell元素
    System.Xml.XmlElement cell = doc.CreateElement("Cell", ss);
    row.AppendChild(cell);
    //创建Data元素
    System.Xml.XmlElement data = doc.CreateElement("Data", ss);
    data.SetAttribute("Type", ss, "Number");
    cell.AppendChild(data);
    System.Xml.XmlText text = doc.CreateTextNode((i + 1).ToString());
    data.AppendChild(text);
    }

    doc.Save(Console.Out);
    Console.WriteLine("\n-----------------------------------------------\n");

    //doc.Save("ExcelDemo.xls");//写入XML文件, 但无法还原为Excel, 少一行xml version指令, 需使用字符流
    System.IO.TextWriter writer = new System.IO.StreamWriter("ExcelDemo.xls",false,Encoding.UTF8);
    doc.Save(writer);
    *
    */
    #endregion

    #region 使用ExcelXmlWriter创建Excel使用的xml, 记得添加ExcelXmlWriter.dll
    string filename =@"testAll.xls";
    CarlosAg.ExcelXmlWriter.Workbook book
    =new CarlosAg.ExcelXmlWriter.Workbook();

    // Specify which Sheet should be opened and the size of window by default
    //book.ExcelWorkbook, 文档更新不及时的错误
    book.ExcelWorkbook.ActiveSheetIndex =1;
    book.ExcelWorkbook.WindowTopX
    =100;
    book.ExcelWorkbook.WindowTopY
    =200;
    book.ExcelWorkbook.WindowHeight
    =7000;
    book.ExcelWorkbook.WindowWidth
    =8000;

    // Some optional properties of the Document
    book.Properties.Author ="CarlosAg";
    book.Properties.Title
    ="My Document";
    book.Properties.Created
    = DateTime.Now;

    // Add some styles to the Workbook
    CarlosAg.ExcelXmlWriter.WorksheetStyle style = book.Styles.Add("HeaderStyle");
    style.Font.FontName
    ="Tahoma";
    style.Font.Size
    =14;
    style.Font.Bold
    =true;
    style.Alignment.Horizontal
    = CarlosAg.ExcelXmlWriter.StyleHorizontalAlignment.Center;
    style.Font.Color
    ="White";
    style.Interior.Color
    ="Blue";
    style.Interior.Pattern
    = CarlosAg.ExcelXmlWriter.StyleInteriorPattern.DiagCross;

    // Create the Default Style to use for everyone
    style = book.Styles.Add("Default");
    style.Font.FontName
    ="Tahoma";
    style.Font.Size
    =10;

    // Add a Worksheet with some data
    CarlosAg.ExcelXmlWriter.Worksheet sheet = book.Worksheets.Add("Some Data");

    // we can optionally set some column settings
    sheet.Table.Columns.Add(new CarlosAg.ExcelXmlWriter.WorksheetColumn(150));
    sheet.Table.Columns.Add(
    new CarlosAg.ExcelXmlWriter.WorksheetColumn(100));

    CarlosAg.ExcelXmlWriter.WorksheetRow row
    = sheet.Table.Rows.Add();
    row.Cells.Add(
    new CarlosAg.ExcelXmlWriter.WorksheetCell("Header 1", "HeaderStyle"));
    row.Cells.Add(
    new CarlosAg.ExcelXmlWriter.WorksheetCell("Header 2", "HeaderStyle"));
    CarlosAg.ExcelXmlWriter.WorksheetCell cell
    = row.Cells.Add("Header 3");
    cell.MergeAcross
    =1; // Merge two cells together
    cell.StyleID ="HeaderStyle";

    row
    = sheet.Table.Rows.Add();
    // Skip one row, and add some text
    row.Index =3;
    row.Cells.Add(
    "Data");
    row.Cells.Add(
    "Data 1");
    row.Cells.Add(
    "Data 2");
    row.Cells.Add(
    "Data 3");

    // Generate 30 rows
    for (int i =0; i <30; i++)
    {
    row
    = sheet.Table.Rows.Add();
    row.Cells.Add(
    "Row "+ i.ToString());
    row.Cells.Add(
    new CarlosAg.ExcelXmlWriter.WorksheetCell(i.ToString(), CarlosAg.ExcelXmlWriter.DataType.Number));
    }

    // Add a Hyperlink
    row = sheet.Table.Rows.Add();
    cell
    = row.Cells.Add();
    cell.Data.Text
    ="Carlos Aguilar Mares";
    cell.HRef
    ="http://www.carlosag.net";
    // Add a Formula for the above 30 rows
    cell = row.Cells.Add();
    cell.Formula
    ="=SUM(R[-30]C:R[-1]C)";

    // Save the file and open it
    book.Save(filename);
    System.Diagnostics.Process.Start(filename);
    #endregion

    #region 调用Xslt转换实例
    /*
    //定义转换对象
    System.Xml.Xsl.XslCompiledTransform transform = new System.Xml.Xsl.XslCompiledTransform();

    //编译样式表
    transform.Load("..\\..\\xsltfile1.xslt");

    //执行转换
    transform.Transform("..\\..\\xsltfile1.xml", "result.html");
    */
    #endregion
    }
    }
    }

    /*Exel范本如下:

    <?xml version="1.0"?>
    <?mso-application progid="Excel.Sheet"?>
    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="
    http://www.w3.org/TR/REC-html40">
    <Styles>
    <Style ss:ID="Default" ss:Name="Normal">
    <Alignment ss:Vertical="Center"/>
    <Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>
    </Style>
    </Styles>
    <Worksheet ss:Name="Sheet1">
    <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="5" x:FullColumns="1"
    x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
    <Row>
    <Cell><Data ss:Type="Number">1</Data></Cell>
    </Row>
    <Row>
    <Cell><Data ss:Type="Number">2</Data></Cell>
    </Row>
    <Row>
    <Cell><Data ss:Type="Number">3</Data></Cell>
    </Row>
    <Row>
    <Cell><Data ss:Type="Number">4</Data></Cell>
    </Row>
    <Row>
    <Cell><Data ss:Type="Number">5</Data></Cell>
    </Row>
    </Table>
    </Worksheet>
    </Workbook>
    */

    三、 关于XML加密和解密的问题

    Xml加密(Xml Encryption)是w3c加密xml的标准, 通过加密xml的初始内容被替换, 但其xml格式仍然被保留.

    对于xml常见的加密方式有: 对称加密法加密xml、对称加密和非对称加密组合法加密xml(对称加密用来对xml内容加密, 而非对称加密用来对前面的密钥进行加密)、第三方公司提供的X.509加密xml.

    常用的是对称加密和非对称加密组合使用, 用来加密xml. 其加密xml的步骤:

    加密步骤:

    1. 选择XML文档中的一个元素(选择根元素的话将加密整个文档)

    2. 使用一个对称加密的密钥加密元素

    3. 使用非对象加密来加密2中的密钥(使用公钥加密, 且公钥加密只有私钥可以解密)

    4. 创建一个EncryptedData元素, 该元素下将包含被加密的数据和被加密的密钥.

    5. 用加密后的元素替换掉初始元素.

    解密步骤:

    1. 在XML文档中选择一个EncryptedData元素

    2. 使用一个非对称密钥来解密密钥(使用私钥解密), 并获得密钥.

    3. 使用2中解密后获得的密钥再次对xml内容进行解密.

    4. 把EncryptedData元素替换成未加密的元素.

    以上这些加密和解密过程的大部分操作, 都可以由.net 2.0中的类自动完成.

    这些类涉及System.Xml(包含xml操作类)、System.Security.Cryptography(包含生成加密密钥的类)、System.Security.Cryptography.Xml(包含完成加密任务的类).

    关于加密解密的示例:

    //Program.cs

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace XmlEncryptAndDecrypt
    {
    class Program
    {
    staticvoid Main(string[] args)
    {
    //模拟PC1上设置Rsa密钥对, 并分发其公钥xml.rsa.public
    SetRsaInPC1();

    //模拟PC2加密xml, 并发送给PC1
    EncryptXMLByPC2();

    //模拟PC1上解密XML
    DecryptXmlByPC1();
    }

    privatestaticvoid SetRsaInPC1()
    {
    //创建非对称密钥对
    #region 保存公钥和私钥到文件, 公钥和密钥都类似于XMl中的节点; 处于安全一般不会这样保存
    /*
    System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
    string publickey = rsa.ToXmlString(false); //公钥
    string privatekey = rsa.ToXmlString(true); //私钥
    rsa.Clear();
    *
    System.IO.StreamWriter sw = new System.IO.StreamWriter("xml.rsa.public",false,Encoding.UTF8);
    sw.Write(publickey);
    sw.Flush();
    sw = new System.IO.StreamWriter("xml.rsa.private", false, Encoding.UTF8);
    sw.Write(privatekey);
    sw.Close();
    */
    #endregion

    #region 保存公钥和私钥到本机的密钥容器中. 注意: 密钥对的创建和读取的代码一样
    //使用CspParameters对象创建或使用密钥容器
    System.Security.Cryptography.CspParameters cp =new System.Security.Cryptography.CspParameters();
    cp.KeyContainerName
    ="Key_Container_XmlRsa"; //设置容器名称
    cp.KeyNumber =1; //设置密钥类型为Exchange
    cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore; //设置密钥容器保存位置为计算机密钥库, 默认是用户密钥库
    //备注: cp通过Rsa对象的构造函数传递, 且若不存在Key_Container_XmlRsa就创建一个, 若存在就使用它.
    #endregion
    //公钥和私钥将直接保存到密钥容器中
    System.Security.Cryptography.RSACryptoServiceProvider rsa =new System.Security.Cryptography.RSACryptoServiceProvider(cp);

    //将公钥存于文件中, 便于向客户机分发
    using (System.IO.StreamWriter sw =new System.IO.StreamWriter("xml.rsa.public", false, Encoding.UTF8))
    {
    sw.Write(rsa.ToXmlString(
    false));
    sw.Flush();
    }
    rsa.Clear();
    //关闭rsa对象
    #region 删除密钥容器
    /*删除密钥容器的方法
    System.Security.Cryptography.CspParameters cp = new System.Security.Cryptography.CspParameters();
    cp.KeyContainerName = "Key_Container_XmlRsa"; //设置容器名称
    cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
    System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(cp);
    rsa.PersistKeyInCsp = false; //关闭持久密钥
    rsa.Clear();
    */
    #endregion
    }

    privatestaticvoid EncryptXMLByPC2()
    {
    //获得PC1的公钥信息, 并把它必成CryptographyServicesProvider对象(也就是用于加密的rsa)
    System.Security.Cryptography.RSACryptoServiceProvider rsa =new System.Security.Cryptography.RSACryptoServiceProvider();
    //载入公钥, 公钥也是XML节点
    System.Xml.XmlDocument pubkey =new System.Xml.XmlDocument();
    pubkey.Load(
    "xml.rsa.public");
    //将公钥编程csp对象
    rsa.FromXmlString(pubkey.OuterXml);

    //加载XML文件, 修改时使用XPath方便
    System.Xml.XmlDocument xmldoc =new System.Xml.XmlDocument();
    System.Xml.XmlDocument encxmldoc
    =new System.Xml.XmlDocument(); //加密后xml
    xmldoc.Load("XMLOperation.xml");
    string xpath ="/configuration/system.web/httpHandlers";
    //System.Xml.XmlNodeList nodes = xmldoc.SelectNodes(xpath);
    System.Xml.XmlElement encelem; //需要指定加密的XML的元素, 如果没有指定则加密整个xml
    if (xpath ==string.Empty)
    {
    encelem
    = xmldoc.DocumentElement; //xmldoc的根元素
    }
    else
    {
    encelem
    = xmldoc.SelectSingleNode(xpath) as System.Xml.XmlElement;
    }

    //使用System.Security.Cryptography.Xml.EncryptedXml类完成数据加密和密码加密, 别忘了添加System.Security.dll程序集
    System.Security.Cryptography.Xml.EncryptedXml encxml =new System.Security.Cryptography.Xml.EncryptedXml(encxmldoc);
    encxml.AddKeyNameMapping(
    "cait", rsa); //将密码用rsa加密, 这里的密码cait其实就是个名字, 这里为简单, 直接硬编码密码进去
    //加密后的数据
    System.Security.Cryptography.Xml.EncryptedData encdata = encxml.Encrypt(encelem, "cait");
    //用加密后的数据替换初始元素
    System.Security.Cryptography.Xml.EncryptedXml.ReplaceElement(encelem, encdata, false);

    Console.WriteLine(
    "----------------------加密后的XMl如下------------------------------");
    xmldoc.Save(Console.Out);
    using (System.IO.StreamWriter sw =new System.IO.StreamWriter("encxmldoc.xml", false, Encoding.UTF8))
    {
    xmldoc.Save(sw);
    }
    }

    privatestaticvoid DecryptXmlByPC1()
    {
    //使用CspParameters对象从密钥容器中读取密钥
    System.Security.Cryptography.CspParameters cp =new System.Security.Cryptography.CspParameters();
    cp.KeyContainerName
    ="Key_Container_XmlRsa"; //设置容器名称
    cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore; //设置密钥容器保存位置为计算机密钥库, 默认是用户密钥库
    System.Security.Cryptography.RSACryptoServiceProvider rsa =new System.Security.Cryptography.RSACryptoServiceProvider(cp);

    //载入已加密的xml
    System.Xml.XmlDocument encxmldoc =new System.Xml.XmlDocument();
    encxmldoc.Load(
    "encxmldoc.xml");
    System.Security.Cryptography.Xml.EncryptedXml encxml
    =new System.Security.Cryptography.Xml.EncryptedXml(encxmldoc);
    encxml.AddKeyNameMapping(
    "cait", rsa);
    //解密所有EncryptedData元素
    encxml.DecryptDocument();

    //显示解密后结果
    encxmldoc.Save(Console.Out);
    using (System.IO.StreamWriter sw =new System.IO.StreamWriter("dencxmldoc.xml", false, Encoding.UTF8))
    {
    encxmldoc.Save(sw);
    }
    }
    }
    }

    最后, 关于.net2.0下加密和解密web.config文件中的某个section

    aspnet_regiis –pef appSettings c:\Inetpu\wwwroot\website

    aspnet_regiis –pdf appSettings c:\Inetpu\wwwroot\website

    注意: 如果目录名称中有空格, 需要使用引号(双引号或单引号)将路径包围起来.

  • 相关阅读:
    hdu 1260 Tickets
    hdu 4738 Caocao's Bridges(桥的最小权值+去重)
    找规律
    C语言快速排序
    数组的初始化方法
    C语言选择排序
    副本机制
    安装完Kali的后续操作
    Bool盲注
    Python中的列表
  • 原文地址:https://www.cnblogs.com/cs_net/p/1949946.html
Copyright © 2020-2023  润新知