• Silverlight中操作Xml


    在Silverlight中操作Xml有三种方式,分别是使用XmlReader(XmlWriter),Linq to xml  ,XmlSerializer(进行Xml的序列化)。

    下面列出微软.net类库提供的读写xml文件个类及其特点:

    类名称

    优点

    缺点

    XmlReader

    快速、高效、可扩展

    只读,只向前,需要人工验证

    XmlDocument

    可往返、可读写、支持XPath筛选

    比XmlReader慢

    XPathNavigator

    可往返,支持XPath和XSLT

    只读

    XPathDocument

    比XmlDocument,优化支持XPath和XSLT

    比XmlReader慢

    一、使用XmlReader读取Xml

    以下为Xml内容

    <?xml version="1.0" encoding="utf-8" ?>
    <Menus>
    <Menu title="常用网址">
    <item name="天下网" url="http://www.netskycn.com" id="1"/>
    <item name="天下网生活论坛" url="http://life.netskycn.com" id="2"/>
    <item name="csdn" url="http://www.csdn.net" id="3"/>
    <item name="我的博客" url="http://blog.csdn.net/zhoufoxcn" id="4"/>
    <item name="百度" url="http://www.baidu.com" id="5"/>
    <item name="Google" url="http://www.google.cn" id="6"/>
    <item name="微软" url="http://www.microsoft.com" id="7"/>
    </Menu>
    <Menu title="娱乐网址">
    <item name="奇虎" url="http://www.qihoo.com" id="12"/>
    <item name="网易" url="http://www.163.com" id="13"/>
    <item name="天涯" url="http://www.tianya.cn" id="14"/>
    </Menu>
    <Menu title="安全网址">
    <item name="360" url="http://www.safe360.com" id="15"/>
    <item name="瑞星" url="http://www.rising.com.cn" id="16"/>
    </Menu>
    </Menus>


    读取这个Xml,这里的stream参数是通过WebClient下载Xml返回的流对象,在上边的对比中已经说了XmlReader需要手动验证,这里就使用了switch对XmlReader的

    NodeType(节点)进行判断.

    使用XmlReader.Create创建一个XmlReader对象;

    使用Read方法循环读取到下一个节点;

    XmlNodeType是枚举类型,表示节点的类型;

    XmlReader.AttributeCount,表示当前节点的属性的数量,xmlReader.MoveToAttribute(i)移动到指定的Attribute,参数可以是属性的索引,也可以是属性的Name;

    XmlReader.Name表示当前节点的名称,XmlReader.Value表示当前节点的文本值.

    private void SetText(Stream stream)
    {
    StringBuilder sbXml = new StringBuilder();
    XmlReader xmlReader = XmlReader.Create(stream);
    while (xmlReader.Read())
    {
    sbXml.Append("节点类型:" + xmlReader.NodeType + "==");
    switch (xmlReader.NodeType)
    {
    case XmlNodeType.XmlDeclaration:
    for (int i = 0; i < xmlReader.AttributeCount; i++)
    {
    xmlReader.MoveToAttribute(i);
    sbXml.Append("属性:" + xmlReader.Name + "=" + xmlReader.Value + "&nbsp;");
    }
    break;
    case XmlNodeType.Attribute:
    for (int i = 0; i < xmlReader.AttributeCount; i++)
    {
    xmlReader.MoveToAttribute(i);
    sbXml.Append("属性:" + xmlReader.Name + "=" + xmlReader.Value + "&nbsp;");

    }
    break;
    case XmlNodeType.CDATA:
    sbXml.Append("CDATA:" + xmlReader.Value + "&nbsp;");

    break;
    case XmlNodeType.Element:
    sbXml.Append("节点名称:" + xmlReader.LocalName+"\n");

    for (int i = 0; i < xmlReader.AttributeCount; i++)
    {
    xmlReader.MoveToAttribute(i);
    sbXml.Append("属性:" + xmlReader.Name + "=" + xmlReader.Value + "&nbsp;");
    }
    break;
    case XmlNodeType.Comment:
    sbXml.Append("Comment:" + xmlReader.Value);
    break;
    case XmlNodeType.Whitespace:
    sbXml.Append("Whitespace:" + "&nbsp;");
    break;
    case XmlNodeType.ProcessingInstruction:
    sbXml.Append("ProcessingInstruction:" + xmlReader.Value);
    break;
    case XmlNodeType.Text:
    sbXml.Append("Text:" + xmlReader.Value);
    break;
    }
    }
    xmlReader.Close();
    txtXml.Text = sbXml.ToString();
    }



    下边看一个读取在项目中可能有此结构的xml.

    xml内容如下:

    <?xml version="1.0" encoding="utf-8" ?> 
    <Persons>
    <Person Name="FLY" Age="21">
    My name is wangyafei.
    </Person>
    </Persons>


    读取代码如下,在读取代码中循环读取了Person节点中的属性(Name和Age).

    private void ReadXml(Stream stream)
    {
    XmlReader xmlReader = XmlReader.Create(stream);
    StringBuilder sbXml = new StringBuilder();
    while (xmlReader.Read())
    {
    sbXml.Append("\n");
    sbXml.Append("节点类型:" + xmlReader.NodeType.ToString());
    switch (xmlReader.NodeType)
    {
    case XmlNodeType.DocumentType:
    break;
    case XmlNodeType.Element:
    //得到节点的名称
    string elementName = xmlReader.Name;
    sbXml.Append("\n");
    sbXml.Append("标签名称:" + elementName);
    //循环节点的属性
    for (int i = 0; i < xmlReader.AttributeCount; i++)
    {
    xmlReader.MoveToAttribute(i);
    sbXml.AppendFormat(string.Format(" 属性名称{0}:属性值{1}", xmlReader.Name, xmlReader.Value));
    }
    break;
    case XmlNodeType.EndElement:
    elementName = xmlReader.Name;
    sbXml.Append(" "+elementName + " element end");
    break;
    default:
    break;
    }
    }
    txtXml.Text = sbXml.ToString();
    }

    下面通过一张图(非原创)看看XmlReader是怎么读取一个Xml的,可以清晰的看到读取的顺序,首先读取xml的声明,然后就是每个标签后边的空白(可能该标签存在文本,那就是读取文本),接着读取接下来的节点部分,接下来(如果节点存在属性则循环读取属性,如果存在嵌套节点则读取嵌套节点的内容,同时可能睡重复本步骤,如果存在文本则在读取完节点的属性后读取文本,然后读取节点的结束标签,一直读取直到整个Xml的结尾标签完毕):

    说完了XmlReader,看看XmlWriter怎么来进行写入Xml。

    以下代码创建一个简单的xml,XmlWriterSettings主要是用于创建Xml时候的一些设置,在这里设置了Indent和IndentChars(这些属性可以通过MSDN获取资料).

    使用XmlWriter.Create方法创建一个XmlWriter对象。

    WriteComment写入一个注释;

    WriteStartElement("ElementName"),创建一个xml节点,和WriteEndElement对应;

    WriteAttributeString("attributeName","attributeValue")给Xml节点添加属性,另外还可以给节点引用一个命名空间

    WriteAttributeString("xmlns","前缀","命名空间的URL","attributeValue"),还可以使用指定的前缀创建节点,

    WriteAttributeString("ElementName","value(命名空间的值)","文本值");

    WriteString("Value"),向节点中写入文本;

    WriteElementString("ElementName","Value"),创建一个包含文本的节点;

    LookupPrefix("value")得到指定值对应的前缀,可以参见WriteAttributeString如何添加一个命名空间;

    Flush提交流;

    Close关闭XmlWriter.

      private void WriteXml(StringBuilder sbXml)
    {
    XmlWriterSettings settings = new XmlWriterSettings();
    //设置Xml是否缩进
    settings.Indent = true;
    //缩进使用的是空格
    settings.IndentChars=(" ");
    //使用Create方法创建一个XmlWriter对象,传入Stream对象和XmlWriterSettings
    using (XmlWriter writer=XmlWriter.Create(sbXml))
    {
    writer.WriteComment("sample XML fragment");
    // 创建一个根节点book
    writer.WriteStartElement("book");
    // 定义一个namespace
    writer.WriteAttributeString("xmlns", "bk", null, "urn:samples");
    //添加一个genre属性,值为novel
    writer.WriteAttributeString("genre", "novel");
    // 添加一个子节点title
    writer.WriteStartElement("title");
    //给节点添加文本
    writer.WriteString("The Handmaid's Tale");
    //title节点结尾
    writer.WriteEndElement();
    // 也是创建一个节点,仅仅包括文本(19.95)
    writer.WriteElementString("price", "19.95");
    //使用命名空间的前缀创建一个ISBN节点
    string prefix = writer.LookupPrefix("urn:samples");
    writer.WriteStartElement(prefix, "ISBN", "urn:samples");
    //写入文本
    writer.WriteString("1-861003-78");
    writer.WriteEndElement();
    // Write the style element (shows a different way to handle prefixes).
    writer.WriteElementString("style", "urn:samples", "hardcover");
    // Write the close tag for the root element.
    writer.WriteEndElement();
    // 提交xmlwriter
    writer.Flush();
    writer.Close();
    }
    txtXml.Text = sbXml.ToString();
    HtmlPage.Window.Alert(sbXml.ToString());
    }

    创建后的内容是:

    <?xml version="1.0" encoding="utf-16"?>
    <!--sample XML fragment-->
    <book xmlns:bk="urn:samples" genre="novel">
    <title>The Handmaid's Tale</title>
    <price>19.95</price>
    <bk:ISBN>1-861003-78</bk:ISBN>
    <bk:style>hardcover</bk:style>
    </book>

    二、使用Linq to xml操作Xml文件

    首先定义一个XDocument(表示一个XML文件对象,当然也可以使用XElement对象),然后创建一个XElement表示节点(可以嵌套多层节点和添加属性XAttribute对象),指定Declaration属性表示Xml的声明部分.

    创建Xml对象:

              //创建Xml对象
    XDocument document = new XDocument();
    //创建注释
    XComment commen = new XComment("创建Xml");
    //定义一个xml处理指令
    XProcessingInstruction instruction = new XProcessingInstruction("xml-stylesheet", "href='mystyle.css' title='Compact' type='text/css'");
    //创建一个Xml几点,并且添加属性Name和Age,添加子节点Company
    XElement PersonElement = new XElement("Person", new XAttribute("Name", "Fly"),new XAttribute("Age", "21"),
    new XElement("Company", new XAttribute("Name", "XXXXXX")));
    //定义xml的声明
    document.Declaration = new XDeclaration("1.0", "utf-8", "true");
    //将注释,处理指令以及节点添加到Document中去。
    document.Add(commen);
    document.Add(instruction);
    document.Add(PersonElement);


    读取Xml:

    通过WebClient下载Xml文件,得到Stream,然后使用XDocument.Load(stream)加载xml,使用XDocument.ToString得到整个xml的内容,当然也可以使用

    XDocument.Element或者XDocument.Elements来得到要获得的节点内容,甚至可以使用Linq to xml进行加载xml。

         void myWebClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
    if (e.Error != null)
    {
    txtXml.Text = e.Error.Message;
    }
    else
    {
    using (Stream stream = e.Result)
    {
    XDocument document = XDocument.Load(stream);
    //得到Person节点
    XElement element = document.Element("Person");
    //获得Person节点的Name属性和Age属性的值
    string name=element.Attribute("Name").Value;
    string age = element.Attribute("Age").Value;
    //SaveOptions.OmitDuplicateNamespaces在进行序列化时移除重复的命名空间声明
    txtXml.Text = document.ToString(SaveOptions.OmitDuplicateNamespaces);
    }
    }
    }

    Linq to xml有几个常用的方法,使得Linq to xml非常的方便:
    Save、CreateReader、ToString和WriteTo方法是比较常用的三个方法:

    2010-05-05_152909


    操作Xml(插入,修改):

    使用这两个方法可以给Element添加节点

                XDocument document = XDocument.Parse("<Persons> <Person > My name is  wangyafei.</Person></Persons>");
    XElement personElement= document.Element("Person");
    personElement.AddAfterSelf("Brithday",DateTime.Now.ToShortDateString());

    得到的结果是

    <Persons>
    <Person>
    My name is wangyafei.
    </Person>
    <Brithday>2011-10-17</Brithday>
    </Persons>

    更新Xml:



    删除Xml使用Remove(XElement)与RemoveAll方法来删除xml。

    三、使用XmlSerializer进行序列化

    XmlSerializer顾名思义Xml序列化,ok,首先创建一个实体类,可以看到给属性加上了[XmlElement]特性,表示一个Xml中对应的节点

    public  class Person
    {
    private string name;
    [XmlElement]
    public string Name
    {
    get { return name; }
    set { name = value; }
    }
    private string email;
    [XmlElement]
    public string Email
    {
    get { return email; }
    set { email = value; }
    }

    }

    xml如下:

    <?xml version="1.0" encoding="utf-8" ?>

    <Person>
    <Name firstName="Super" lastName="Fly">MyFly</Name>
    <Email>wangyafei_it@163.com</Email>
    </Person>

    下面进行序列化:

    创建一个webservice,添加方法,其实这个方法才是重点,实例化一个XmlSerializer参数就是我们的Xml对应的序列化的实体类,然后调用Deserialize进行反序列化

    然后转换为真正的类型,即可:

          [OperationContract]
    public Person ResolveXmlSerializer(Stream stream)
    {
    XmlSerializer serializer = new XmlSerializer(typeof(Person));
    Person person = serializer.Deserialize(stream) as Person;
    return person;
    }

    通过WebClient下载Xml然后调用此方法:

      private void btnDownLoad_Click(object sender, RoutedEventArgs e)
    {
    Uri endPoint = new Uri("http://localhost:4276/Images/PersonTest.xml");
    WebClient client = new WebClient();
    client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
    client.OpenReadAsync(endPoint);

    }

    void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
    XmlServiceClient serviceClient = new XmlServiceClient();
    serviceClient.ResolveXmlSerializerCompleted += new EventHandler<XmlService.ResolveXmlSerializerCompletedEventArgs>(serviceClient_Resolv eXmlSerializerCompleted);
    byte[] bytes=new byte[e.Result.Length];
    e.Result.Read(bytes,0,bytes.Length);
    serviceClient.ResolveXmlSerializerAsync(bytes);
    }

    void serviceClient_ResolveXmlSerializerCompleted(object sender, XmlService.ResolveXmlSerializerCompletedEventArgs e)
    {
    Person person = e.Result;
    HtmlPage.Window.Alert("Name:" + person.Name + "; Email:" + person.Email);
    }



    好了,整个Silverlight中访问xml已经基本搞定了,多多指点。

  • 相关阅读:
    LNOI2014LCA(树链剖分+离线操作+前缀和)
    CDQ分治与整体二分学习笔记
    BJWC2018上学路线
    NOIP2013火柴排队
    SHOI2008仙人掌图(tarjan+dp)
    作诗(分块)
    COGS314. [NOI2004] 郁闷的出纳员
    bzoj 1691: [Usaco2007 Dec]挑剔的美食家
    COGS1533.[HNOI2002]营业额统计
    bzoj1208: [HNOI2004]宠物收养所
  • 原文地址:https://www.cnblogs.com/ListenFly/p/2206719.html
Copyright © 2020-2023  润新知