LinqToXml高级用法介绍

一、函数构造

什么是函数构造?其是指通过单个语句构建XML树的能力。

那么它有什么作用呢?

作用1、用单个表达式快速创建复杂的XML树

见实例代码CreateXml( ):

复制代码
public static XElement CreateXml()
        {
            XElement emp = new XElement("Employees",
                new XElement("Employee",new XAttribute("id","1"),
                                           new XAttribute("Dept","00001"),
                                           new XElement("name","Scott"),
                                           new XElement("Address",
                                               new XElement("Street","555 main st."),
                                               new XElement("City","Wellington"),
                                               new XElement("State","FL"),
                                               new XElement("Zip","33144")
                                               ),
                                           new XElement("Title","All things Techy"),
                                           new XElement("HireDate","02/05/2007"),
                                           new XElement("Gender","M")
                    )
                );
            return emp;
        }
复制代码

输出结果:

复制代码
<Employees>
  <Employee id="1" Dept="00001">
    <name>Scott</name>
    <Address>
      <Street>555 main st.</Street>
      <City>Wellington</City>
      <State>FL</State>
      <Zip>33144</Zip>
    </Address>
    <Title>All things Techy</Title>
    <HireDate>02/05/2007</HireDate>
    <Gender>M</Gender>
  </Employee>
</Employees>
复制代码

作用2、通过查询表达式容易地控制所构建的XML树,更方便的修改和保存XML树。

见实例代码EditXml( )

复制代码
public static XElement EditXml()
        {
            XElement emp = XElement.Load(@"output.xml");
            emp = new XElement("Employee",
                       emp.Element("Employee").Element("name"),
                       from atts in emp.Element("Employee").Attributes() where atts.Name == "id" select new XElement(atts.Name, (string)atts)
                     );
            return emp;
        }
复制代码

输出结果:

<Employee>
  <name>Scott</name>
  <id>1</id>
</Employee>

二、批注

什么是批注?

批注是与一段文本相关联的说明性的注释。但批注是不可见的

实例代码AddAnnotation( ):

复制代码
public static XElement AddAnnotation()
        {
            _2Annotation anno = new _2Annotation(5);
            XElement root = XElement.Load("output.xml");
            root.AddAnnotation(anno);
            root.AddAnnotation("批注:1");
            root.AddAnnotation("批注:2");
            //批注不可见,但可通过下面这种方式获取批注值
            _2Annotation newAnno = root.Annotation<_2Annotation>();
            Console.WriteLine("批注值:" + newAnno.Val1);
            IEnumerable<string> stringList = root.Annotations<string>();
            foreach (string item in stringList)
            {
                Console.WriteLine(item);
            }

            return root;
        }
复制代码

输出结果:

批注值:5
批注:1
批注:2

三、轴

Linq To Xml轴是干什么用的?

在一个xml数中遍历并返回多个节点的值。其返回元素和属性的集合。

轴的实现方法有哪些呢

方法1:Ancestors

其返回指定节点的上级元素的集合

见代码Ancestors():

复制代码
private XElement _XmlE;
        public _3Zhou()
        {
            _XmlE = new XElement("Employees",
                  new XElement("Employee",
                         new XElement("Name",
                             new XElement("FirstName", "Gong"),
                             new XElement("MiddleName", "Wen"),
                             new XElement("LastName", "Tao")
                             ),
                         new XElement("Sex", "")
                       ),
                new XElement("Employee",
                      new XElement("Name",
                          new XElement("FirstName", "Zhao"),
                          new XElement("MiddleName", "Si"),
                          new XElement("LastName", "Si")
                          ),
                     new XElement("Sex", "Girl")
                          )
                 );
        }
        public IEnumerable<XElement> Ancestors()
        {
            return _XmlE.Elements("Employee").Elements("Name").Ancestors<XElement>();
        }
复制代码

见输出:

QQ截图20130825105650

同时它还包含一个重载方法,即Ancestors(XName name), name是使集合只返回指定name的元素。

见代码Ancestors(string xname):

public IEnumerable<XElement> Ancestors(string xname)
        {
            return _XmlE.Elements("Employee").Elements("Name").Ancestors<XElement>(xname);
        }

见输出:

QQ截图20130825105914

方法2:Descendants

与Ancestors方法相反,其返回指定元素的后续元素的集合

见代码:

public IEnumerable<XElement> Descendants()
        {
            return _XmlE.Elements("Employee").Elements("Name").Descendants<XElement>();
        }

见输出:

QQ截图20130825105650

它同时也包含一个重载方法Descendants(string xname),作用和Ancestors方法一样

方法3:AncestorsAndSelf

方法4:DescendantsAndSelf

方法3和方法4同方法1和2,不过返回的集合中包含了自身元素而已。

四、事件

事件是指,当你对xml树进行修改时,linq to xml事件会提供通知。主要包含两个事件,一个是changing一个是changed,changing就是在改变之前触发,changed是改变之后触发。但如果是修改值得话,会触发两遍,因为这是一次删除和一次插入的操作。

见代码:

复制代码
public _4Event()
        {
            _XmlE = new XElement("Employees",
                  new XElement("Employee",
                         new XElement("Name",
                             new XElement("FirstName", "Gong"),
                             new XElement("MiddleName", "Wen"),
                             new XElement("LastName", "Tao")
                             ),
                         new XElement("Sex", "")
                       ),
                new XElement("Employee",
                      new XElement("Name",
                          new XElement("FirstName", "Zhao"),
                          new XElement("MiddleName", "Si"),
                          new XElement("LastName", "Si")
                          ),
                     new XElement("Sex", "Girl")
                          )
                 );
            _XmlE.Changing += _XmlE_Changing;
            _XmlE.Changed += _XmlE_Changed;
            _XmlE.Element("Employee").Elements("Name").Elements("FirstName").First().AddAfterSelf(new XElement("NickName", "taoGe"));
        }

        void _XmlE_Changed(object sender, XObjectChangeEventArgs e)
        {
            Console.WriteLine("changed event raised");
            XElement newEl = (XElement)sender;
            Console.WriteLine("Sender:" + newEl.Name);
            Console.WriteLine("Object Change:" + e.ObjectChange);
        }

        void _XmlE_Changing(object sender, XObjectChangeEventArgs e)
        {
            //    throw new NotImplementedException();
            Console.WriteLine("changing event raised");
            XElement newEl = (XElement)sender;
            Console.WriteLine("Sender:" + newEl.Name);
            Console.WriteLine("Object Change:" + e.ObjectChange);
        }
复制代码

见输出:

QQ截图20130825110134

五、流处理Xml文档

这个主要用于处理大型xml文档和树的。因为大型xml文档会非常消耗内存。而流处理的工作原理是从xml源中读取一小片段数据,进行处理,从而减少内存的使用量。

其具体实现是使用XmlReader类来快速遍历XML文档以寻找所需要的节点,然后调用ReadFrom方法从源读取信息并填充到目标xml片段。

见代码:

复制代码
public static IEnumerable<XElement> StreamSalesOrders(string uri)
        {
            using (XmlReader reader = XmlReader.Create(uri))
            {
                XElement name = null;
                XElement order = null;
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "SalesPerson")
                    {
                        while (reader.Read())
                        {
                            if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name")
                            {
                                name = XElement.ReadFrom(reader) as XElement;
                                break;
                            }
                        }
                        while (reader.Read())
                        {
                            if (reader.NodeType == XmlNodeType.EndElement)
                            {
                                break;
                            }
                            if (reader.NodeType == XmlNodeType.Element && reader.Name == "Order")
                            {
                                order = XElement.ReadFrom(reader) as XElement;
                                if (order != null)
                                {
                                    XElement tmpRoot = new XElement("TempRoot", new XElement(name));
                                    tmpRoot.Add(order);
                                    // yield return 提供了迭代器一个比较重要的功能,
                                        //即取到一个数据后马上返回该数据,不需要全部数据装入数列完毕,这样有效提高了遍历效率。
                                        yield return order;
                                }
                            }
                        }
                    }
                }
            }
        }
复制代码

见输出:

QQ截图20130825114526

源码下载:

喜欢就动动手指点下推荐吧,您的支持是我分享的动力!

posted @   flowbywind  阅读(1568)  评论(4编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示