static void Main(string[] args) { #if false // X-DOM Overview 文档对象模型 概述 { XElement config = XElement.Parse( @"<configuration> <client enabled='true'> <timeout>30</timeout> </client> </configuration>"); foreach (XElement child in config.Elements()) { child.Name.Dump("Child element name"); } XElement client = config.Element("client"); bool enabled = (bool)client.Attribute("enabled"); // Read attribute enabled.Dump("enabled attribute"); client.Attribute("enabled").SetValue(!enabled); // Update attribute int timeout = (int)client.Element("timeout"); // Read element timeout.Dump("timeout element"); client.Element("timeout").SetValue(timeout * 2); // Update element client.Add(new XElement("retries", 3)); // Add new elememt } // Instantiation X-DOM 实例化 X-DOM { // 方法 添加 元素节点 节点值 属性 熟悉值 XElement lastName = new XElement("lastname", "Bloggs"); lastName.Add(new XComment("nice name")); XElement customer = new XElement("customer"); customer.Add(new XAttribute("id", 123)); customer.Add(new XElement("firstname", "Joe")); customer.Add(lastName); customer.Dump(); // Functional Construction 函数式构建 new XElement("customer", new XAttribute("id", 123), new XElement("firstname", "joe"), new XElement("lastname", "bloggs", new XComment("nice name") ) ); // Fucntional Construction from Database Query 为每个实体对象 创建 元素节点 NutshellEntities dataContext = new NutshellEntities(); new XElement("customers", from c in dataContext.Customer select new XElement("customer", new XAttribute("id", c.ID), new XElement("name", c.Name, new XComment("nice name")))); // Automatic Deep Cloing 自动深度克隆 var address = new XElement("address", new XElement("street", "Lawley St"), new XElement("town", "North Beach") ); var customer1 = new XElement("customer1", address); var customer2 = new XElement("customer2", address); customer1.Element("address").Element("street").Value = "Another St"; Console.WriteLine(customer2.Element("address").Element("street").Value); } #elif false // Navigating and Querying 导航查询 { // FirstNode LastNode and Nodes var bench = new XElement("bench", new XElement("toolbox", new XElement("handtool", "Hammer"), new XElement("handtool", "Rasp") ), new XElement("toolbox", new XElement("handtool", "Saw"), new XElement("powertool", "Nailgun") ), new XComment("Be careful with the nailgun") ); bench.FirstNode.Dump("FirstNode"); bench.LastNode.Dump("LastNode"); foreach (XNode node in bench.Nodes()) { Console.WriteLine(node.ToString(SaveOptions.DisableFormatting) + "."); // toolbox = HammerRasp } // toolbox = SawNailgun // Enumerating Elements 检索元素 foreach (XElement e in bench.Elements()) { Console.WriteLine(e.Name + "=" + e.Value); } // Quering Elements IEnumerable <string> toolboxWithNailgun = from toolbox in bench.Elements() where toolbox.Elements().Any(tool => tool.Value == "Nailgun") select toolbox.Value; var handTools = from toolbox in bench.Elements() from tool in toolbox.Elements() where tool.Name == "handtool" select tool.Value; int toolboxCount = bench.Elements("toolbox").Count(); var handTools2 = from tool in bench.Elements("toolbox").Elements("handtool") select tool.Value.ToUpper(); toolboxWithNailgun.Dump("The toolbox with the nailgun"); handTools.Dump("The hand tools in all toolboxes"); toolboxCount.Dump("Number of toolboxes"); handTools2.Dump("The hand tools in all toolboxes"); XElement singnal = bench.Element("toolbox").Element("xyc"); string nullableValue = singnal?.Value; // Quering Elements - Recursive // Descendants 返回所有叶子节点 并 可筛选 // DescendantNodes 返回包含所有的父节点 和 叶子节点 bench.Descendants("handtool").Count().Dump(); foreach (XNode node in bench.DescendantNodes()) { Console.WriteLine(node.ToString(SaveOptions.DisableFormatting)); } ( from c in bench.DescendantNodes().OfType <XComment>() where c.Value.Contains("careful") orderby c.Value select c.Value ).Dump("Comments anywhere in the X-DOM containing the word 'careful'"); } #elif false // Updating X-DOM 更新 X-DOM { // SetValue Replaces Child Content XElement settings = new XElement("settings", new XElement("timeout", 30)); settings.Dump("Original XML"); settings.SetValue("blah"); settings.Dump("Notice the timeout node has disappeared"); // SetElementValue 添加或覆盖 XElement settings2 = new XElement("settings"); settings.SetElementValue("timeout", 30); settings2.Dump("Adds child element"); settings.SetElementValue("timeout", 60); settings2.Dump("Updates child element"); // AddAfterSelf Remove Replace XElement items = new XElement("items", new XElement("one"), new XElement("three") ); items.Dump("Original XML"); items.FirstNode.AddAfterSelf(new XElement("two")); items.Dump("After calling items.FirstNode.AddAfterSelf"); items.FirstNode.ReplaceWith(new XComment("One was here")); items.Dump("After calling ReplaceWith"); XElement contacts = XElement.Parse(@" <contacts> <customer name='Mary'/> <customer name='Chris' archived='true'/> <supplier name='Susan'> <phone archived='true'>012345678<!--confidential--></phone> </supplier> </contacts>"); contacts.Dump("Before"); contacts.Elements("customer").Remove(); contacts.Dump("After"); contacts.Dump("Before"); contacts.Elements() // <customer name='Chris' archived='true'/> 被移除 .Where(e1 => (bool?)e1.Attribute("archived") == true) .Remove(); contacts.Dump("After"); contacts.Dump("Before"); contacts.Descendants() // 所有 属性archived的值为 true 的元素被移除 .Where(e2 => (bool?)e2.Attribute("archived") == true) .Remove(); contacts.Dump("After"); contacts.Dump("Before"); contacts.Elements() .Where(e3 => e3.DescendantNodes().OfType <XComment>().Any(c => c.Value == "confidential")) .Remove(); contacts.Dump("After"); contacts.Descendants().OfType <XComment>().Remove(); // 移除整个树🌳中的注释节点 contacts.DescendantNodes().OfType <XComment>().Remove(); // Get and Set Value var e = new XElement("date", DateTime.Now); e.SetValue(DateTime.Now.AddDays(1)); e.Value.Dump(); DateTime dt = (DateTime)e; XAttribute a = new XAttribute("resolution", 1.234); double res = (double)a; // Nullables 可空类型 int? timeout = (int?)e.Element("timeout"); double resolution = (double?)e.Attribute("resolution") ?? 1.0; var nullXe = new XElement("Empty"); try { int timeout1 = (int)nullXe.Element("timeout"); } catch (Exception ex) { ex.Message.Dump("Element (\"timeout\") returns null so the result cannot be cast to int"); } int?timeout2 = (int?)nullXe.Element("timeout"); timeout2.Dump("Casting to a nullable type solve this problem"); var data = XElement.Parse(@" <data> <customer id='1' name='Mary' credit='100' /> <customer id='2' name='John' credit='150' /> <customer id='3' name='Anne' /> </data>"); IEnumerable <string> query = from cust in data.Elements() where (int?)cust.Attribute("credit") > 100 // 属性值转换为 nullable,避免 NullReferenceException select cust.Attribute("name").Value; query.Dump(); IEnumerable <string> query2 = from cust in data.Elements() where cust.Attributes("credit").Any() && (int)cust.Attribute("credit") > 100 select cust.Attribute("name").Value; query2.Dump(); // XText 与 XElement 混合内容 XElement summary = new XElement("summary", new XText("An XAttribute is "), new XElement("bold", "not"), new XText(" an XNode") ); summary.Dump(); // An XAttribute is not an XNode { var e1 = new XElement("test", "Hello"); e1.Add("World"); var e2 = new XElement("test", "Hello", "World"); var e3 = new XElement("test", new XText("Hello"), new XText("World")); e1.Dump(); e2.Dump(); e3.Dump(); // 均输出 Hello World e1.Nodes().Count().Dump("Number of children in e1"); // 均为 2 e2.Nodes().Count().Dump("Number of children in e2"); e3.Nodes().Count().Dump("Number of children in e3"); } } #elif false // Documents and Declarations 文档和声明 { // Building an XHTML document 建立一个XHTML 文档{ { var styleInstruction = new XProcessingInstruction( "xml-stylesheet", "href='styles.css' type='text/css'"); var docType = new XDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", null); XNamespace ns = "http://www.w3.org/1999/xhtml"; var root = new XElement(ns + "html", new XElement(ns + "head", new XElement(ns + "title", "An XHTML page")), new XElement(ns + "body", new XElement(ns + "h1", "This is a heading."), new XElement(ns + "p", "This is some content.")) ); var doc = new XDocument( new XDeclaration("1.0", "utf-8", "no"), new XComment("Reference a stylesheet"), styleInstruction, docType, root ); string tempPath = Path.Combine(Path.GetTempPath(), "sample.html"); doc.Save(tempPath); Process.Start(tempPath); // This will display the page in IE or FireFox File.ReadAllText(tempPath).Dump(); doc.Root.Name.LocalName.Dump("Root element's local name"); XElement bodyNode = doc.Root.Element(ns + "body"); (bodyNode.Document == doc).Dump("bodyNode.Document == doc"); (doc.Root.Parent == null).Dump("doc.Root.Parent is null"); foreach (XNode node in doc.Nodes()) { Console.Write(node.Parent == null); } } // Declarations 声明 { var doc = new XDocument( new XDeclaration("1.0", "utf-16", "yes"), new XElement("test", "data") ); string tempPath = Path.Combine(Path.GetTempPath(), "test.xml"); doc.Save(tempPath); File.ReadAllText(tempPath).Dump(); var output = new StringBuilder(); var settings = new XmlWriterSettings { Indent = true }; using (XmlWriter xw = XmlWriter.Create(output, settings)) doc.Save(xw); output.ToString().Dump("Notice the encoding is utf-16 and not utf-8"); } // Names and Namespaces 名称和命名空间 { // 直接使用 {} new XElement("{http://domain.com/xmlspace}customer", "Bloggs"); // 使用 XName 和 XNamespace XName localName = "customer"; localName.Dump("localName"); XName fullName1 = "{http://domain.com/xmlspace}customer"; fullName1.Dump("fullname1"); XNamespace ns = "http://domain.com/xmlspace"; XName fullName2 = ns + "customer"; fullName2.Dump("fullname2 - same result, but cleaner and more efficient"); var data = new XElement(ns + "data", new XAttribute(ns + "id", 123) ); data.Dump(); XElement x = data.Element(ns + "customer"); // OK XElement y = data.Element("customer"); // null // 为每一个元素分配命名空间 var data2 = new XElement(ns + "data", new XElement("customer", "Bloggs"), new XElement("purchase", "Bicycle") ); data.Dump("Before"); foreach (XElement e in data2.DescendantsAndSelf()) { if (e.Name.Namespace == "") { e.Name = ns + e.Name.LocalName; } } data.Dump("After"); // Prefixes 前缀 XNamespace ns1 = "http://domain.com/space1"; XNamespace ns2 = "http://domain.com/space2"; var mix = new XElement(ns1 + "data", new XElement(ns2 + "element", "value"), new XElement(ns2 + "element", "value"), new XElement(ns2 + "element", "value") ); mix.Dump("Without prefixes"); mix.SetAttributeValue(XNamespace.Xmlns + "ns1", ns1); mix.SetAttributeValue(XNamespace.Xmlns + "ns2", ns2); mix.Dump("With prefixes"); XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; var nil = new XAttribute(xsi + "nil", true); var cust = new XElement("customers", new XAttribute(XNamespace.Xmlns + "xsi", xsi), new XElement("customer", new XElement("lastname", "Bloggs"), new XElement("dob", nil), new XElement("credit", nil) ) ); cust.Dump(); } } #elif true // Annotations 注解 { #if true { XElement e = new XElement("test"); e.AddAnnotation("Hello"); e.Annotation <string>().Dump("String annotations"); e.RemoveAnnotations <string>(); e.Annotation <string>().Dump("String annotations"); } { XElement e = new XElement("test"); e.AddAnnotation(new Customer { ID = 13, Name = "Linaggan", Purchase = null }); e.Annotations <Customer>().First().Name.Dump(); e.RemoveAnnotations <Customer>(); e.Annotations <Customer>().Count(); } #endif } // Projecting into an X-DOM 将数据映射到X-DOM中 { var customers = new XElement("Customers", new XElement("Customer", new XAttribute("id", 13), new XElement("name", "Lianggan13"), new XElement("buys", 3))); NutshellEntities dataContext = new NutshellEntities(); var customers2 = new XElement("Customers", from c in dataContext.Customer.ToList() // 注:此处 要有 ToList() select new XElement("Customer", new XAttribute("id", c.ID), new XElement("name", c.Name), new XElement("buys", (c.Purchase.Count)))); { IEnumerable <XElement> queryxe = from c in dataContext.Customer select new XElement("Customer", new XAttribute("id", c.ID), new XElement("name", c.Name), new XElement("buys", c.Purchase.Count)); //var customers3 = new XElement("Customers", queryxe.AsQueryable()); } { // 在查询的客户信息中还包含客户最近的高价购买记录的详细信息 (排除空元素) IEnumerable <XElement> queryxe2 = from c in dataContext.Customer let lastBigBuy = ( from p in c.Purchase where p.Price > 1000 orderby p.Date descending select p ).FirstOrDefault() select new XElement("Customer", new XAttribute("id", c.ID), new XElement("name", c.Name), new XElement("buys", c.Purchase.Count), lastBigBuy == null ? null : // 客户没有lastBigBuy时,返回null,其内容自动被忽略 new XElement("LastBigBuy", new XElement("Description", lastBigBuy.Description), new XElement("Price", lastBigBuy.Price) )); // var customers4 = new XElement("Customers", queryxe2); } // Transfer X-DOM 转换 X-DOM // 获取项目文件中的文件信息 XElement project = XElement.Parse(@" <Project DefaultTargets=""Build"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> <PropertyGroup> <Platform Condition="" '$(Platform)' == '' "">AnyCPU</Platform> <ProductVersion>9.0.11209</ProductVersion> </PropertyGroup> <ItemGroup> <Compile Include=""ObjectGraph.cs"" /> <Compile Include=""Program.cs"" /> <Compile Include=""Properties\AssemblyInfo.cs"" /> <Compile Include=""Tests\Aggregation.cs"" /> <Compile Include=""Tests\Advanced\RecursiveXml.cs"" /> </ItemGroup> </Project>"); XNamespace ns = project.Name.Namespace; var queryFiles = new XElement("ProjectReport", from complieItem in project.Elements(ns + "ItemGroup").Elements(ns + "Compile") let include = complieItem.Attribute("Include") where include != null select new XElement("File", include.Value)); queryFiles.Save(Directory.GetCurrentDirectory() + "\\" + "Files.xml"); var paths = from complieItem in project.Elements(ns + "ItemGroup").Elements(ns + "Compile") let include = complieItem.Attribute("Include") where include != null select include.Value; var queryFoderFiles = new XElement("ProjectReport", ExpandPaths(paths)); queryFoderFiles.Save(Directory.GetCurrentDirectory() + "\\" + "FoderFiles .xml"); } #endif Console.ReadKey(); }