140 likes | 229 Views
LINQ to XML : A Brief Overview. Pavel Je žek. LINQ to XML – Example XML.
E N D
LINQ to XML: A Brief Overview Pavel Ježek
LINQ to XML – Example XML <contacts> <contact> <name>Patrick Hines</name> <phonetype="home">206-555-0144</phone> <phonetype="work">425-555-0145</phone> <address> <street1>123 Main St</street1> <city>Mercer Island</city> <state>WA</state> <postal>68042</postal> </address> <netWorth>10</netWorth> </contact> <contact> <name>Gretchen Rivas</name> <phonetype="mobile">206-555-0163</phone> <address> <street1>123 Main St</street1> <city>Mercer Island</city> <state>WA</state> <postal>68042</postal> </address> <netWorth>11</netWorth> </contact> <contact> <name>Scott MacDonald</name> <phonetype="home">925-555-0134</phone> <phonetype="mobile">425-555-0177</phone> <address> <street1>345 Stewart St</street1> <city>Chatsworth</city> <state>CA</state> <postal>91746</postal> </address> <netWorth>500000</netWorth> </contact></contacts> Pavel JežekLINQ to XML
LINQ to XML – Creating XML via DOM (without XLinq) XmlDocument doc = newXmlDocument();XmlElement name = doc.CreateElement("name");name.InnerText = "Patrick Hines";XmlElement phone1 = doc.CreateElement("phone");phone1.SetAttribute("type", "home");phone1.InnerText = "206-555-0144"; XmlElement phone2 = doc.CreateElement("phone");phone2.SetAttribute("type", "work");phone2.InnerText = "425-555-0145"; XmlElement street1 = doc.CreateElement("street1"); street1.InnerText = "123 Main St";XmlElement city = doc.CreateElement("city");city.InnerText = "Mercer Island";XmlElement state = doc.CreateElement("state");state.InnerText = "WA";XmlElement postal = doc.CreateElement("postal");postal.InnerText = "68042";XmlElement address = doc.CreateElement("address");address.AppendChild(street1);address.AppendChild(city);address.AppendChild(state);address.AppendChild(postal);XmlElement contact = doc.CreateElement("contact");contact.AppendChild(name);contact.AppendChild(phone1);contact.AppendChild(phone2);contact.AppendChild(address);XmlElement contacts = doc.CreateElement("contacts");contacts.AppendChild(contact);doc.AppendChild(contacts); Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Creating XML via XLinq • Functional construction: XElement contacts = newXElement("contacts", newXElement("contact", newXElement("name", "Patrick Hines"), newXElement("phone", "206-555-0144", newXAttribute("type", "home")), newXElement("phone", "425-555-0145", newXAttribute("type", "work")), newXElement("address",newXElement("street1", "123 Main St"),newXElement("city", "Mercer Island"),newXElement("state", "WA"),newXElement("postal", "68042") ) )); • Imlicitly no XML document • Can be added if some processing information is needed: XDocument contactsDoc = newXDocument(newXDeclaration("1.0", "UTF-8", "yes"),newXComment("XLinq Contacts XML Example"),newXProcessingInstruction("MyApp", "123-44-4444"),newXElement("contacts", newXElement("contact",newXElement("name", "Patrick Hines"), … Resulting XML: <?xmlversion="1.0" standalone="yes"?><!--XLinq Contacts XML Example--><?MyApp 123-44-4444?><contacts> <contact> <name>Patrick Hines</name> … Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – XML Namespaces • There is a support for XML namespaces, but namespace aliases are always expanded into full names • Creating element from a “http://myCompany.com” namespace: XElement contacts = newXElement("{http://myCompany.com}contacts", …); • Instead of explicit alias support, existing language facilities should be used. Typical pattern: string myNs = "{http://mycompany.com}";XElement contacts =newXElement(myNs+"contacts",newXElement(myNs+"contact",newXElement(myNs+"name", "Patrick Hines"),newXElement(myNs+"phone", "206-555-0144", newXAttribute("type", "home")), ) ) ); • Results in following XML: <contactsxmlns="http://mycompany.com"> <contact> <name>Patrick Hines</name> <phonetype="home">206-555-0144</phone> </contact></contacts> Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Loading Existing XML Data • From string: XElement contacts = XElement.Parse(@"<contacts> <contact> <name>Patrick Hines</name> <phone type=""home"">206-555-0144</phone> <phone type=""work"">425-555-0145</phone> <address> <street1>123 Main St</street1> <city>Mercer Island</city> <state>WA</state> <postal>68042</postal> </address> <netWorth>10</netWorth> </contact></contacts>"); • From file: XElement contactsFromFile = XElement.Load(@"c:\myContactList.xml"); Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Creating XElements • XElement’s constructor: public XElement(XName name, paramsobject[] contents) • Any of the parameters passed to contents can be: • A string, which is added as text content • An XElement, which is added as a child element • An XAttribute, which is added as an attribute • An XProcessingInstruction, XComment, or XCData, which is added as child content • An IEnumerable, which is enumerated, and these rules are applied recursively • Anything else, ToString() is called and the result is added as text content • null, which is ignored Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Adding IEnumerables to XElement class Person {public string Name; public string[] PhoneNumbers;} var persons = new [] { newPerson { Name="Patrick Hines", PhoneNumbers = newstring[] {"206-555-0144", "425-555-0145"} }, newPerson { Name="Gretchen Rivas", PhoneNumbers = newstring[] {"206-555-0163"} } }; • Following code using Standard Query Operators on IEnumerable<T> can be used to transform a datastructure to XML: XElement contacts = newXElement("contacts",from p in personsselectnewXElement("contact",newXElement("name", p.Name),from ph in p.PhoneNumbersselectnewXElement("phone", ph))); Console.WriteLine(contacts); Output: <contacts> <contact> <name>Patrick Hines</name> <phone>206-555-0144</phone> <phone>425-555-0145</phone> </contact> <contact> <name>Gretchen Rivas</name> <phone>206-555-0163</phone> </contact> </contacts> Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Element Text as Value (1) • XElement (text inside XElement) can be explicitly converted to a value: XElement name = newXElement("name", "Patrick Hines"); string nameString = (string) name; Console.WriteLine(nameString); • ToString() returns the XML representation of the whole element: string nameString = name.ToString(); Console.WriteLine(nameString); • Explicit type operators are provided for following types:string, bool, bool?, int, int?, uint, uint?, long, long?, ulong, ulong?, float, float?, double, double?, decimal, decimal?, DateTime, DateTime?, TimeSpan, TimeSpan?, GUID, GUID? Output: Patrick Hines Output: <name>Patrick Hines</name> Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Element Text as Value (2) • All element text is merged together: XElementxhtml = new XElement(“body", 1234, new XElement("br", null), 5678, "some text", new XElement("br", ""), new XElement("em", "EMPHASED TEXT"), "other text\nwith newline" ); Console.WriteLine(nameString); Console.WriteLine((string) nameString); Output: <body>1234<br />5678some text<br></br><em>EMPHASED TEXT</em>other text with newline</body> Output: 12345678some textEMPHASED TEXTother text with newline Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Traversing XML • XML data: <contact> Met in 2005. <name>Patrick Hines</name> <phone>206-555-0144</phone> <phone>425-555-0145</phone> <!-- Avoid whenever possible --> </contact> • Code examples: foreach (c in contact.Content()) {Console.WriteLine(c); } foreach (c in contact.Content<XElement>()) {Console.WriteLine(c) } foreach (x in contact.Elements()) {Console.WriteLine(x); } foreach (x in contact.Elements("phone")) {Console.WriteLine(x); } XElement name = contact.Element("name"); string name = (string) contact.Element("name"); Met in 2005.<name>Patrick Hines</name><phone>206-555-0144</phone><phone>425-555-0145</phone><!-- Avoid whenever possible --> <name>Patrick Hines</name><phone>206-555-0144</phone><phone>425-555-0145</phone> <phone>206-555-0144</phone><phone>425-555-0145</phone> Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML – Manipulating XML • Code samples: XElement mobilePhone = newXElement("phone", "206-555-0168"); contact.Add(mobilePhone); contact.AddFirst(mobilePhone); contact.Add(newXElement("address", newXElement("street", "123 Main St"),newXElement("city", "Mercer Island"),newXElement("state", "WA"),newXElement("country", "USA"),newXElement("postalCode", "68042") )); XElement mobilePhone = newXElement("phone", "206-555-0168"); XElement firstPhone = contact.Element("phone"); firstPhone.AddAfterThis(mobilePhone); contact.Element("phone").Remove(); contact.Elements("phone").Remove(); contact.Element("address").ReplaceContent(newXElement("street", "123 Brown Lane"),newXElement("city", "Redmond"),newXElement("state", "WA"), newXElement("country", "USA"),newXElement("postalCode", "68072")); contact.SetElement("phone", "425-555-0155"); contact.SetElement(“phone", null); Pavel JežekC# 3.0 and .NET 3.5
LINQ to XML - Queries • Example – flattening contacts: newXElement("contacts",from c in contacts.Elements("contact")selectnewobject[] {newXComment("contact"),newXElement("name", (string)c.Element("name")), c.Elements("phone"),newXElement("address", c.Element("address")) }); • Results in: <contacts> <!-- contact --> <name>Patrick Hines</name> <phonetype="home">206-555-0144</phone> <phonetype="work">425-555-0145</phone> <address> <address> <state>WA</state> </address> </address> <!-- contact --> <name>Gretchen Rivas</name> <address> <address> <state>WA</state> </address> </address> <!-- contact --> <name>Scott MacDonald</name> <phonetype="home">925-555-0134</phone> <phonetype="mobile">425-555-0177</phone> ... <contacts> <contact> <name>Patrick Hines</name> <phonetype="home">206-555-0144</phone> <phonetype="work">425-555-0145</phone> <address> <street1>123 Main St</street1> <city>Mercer Island</city> <state>WA</state> <postal>68042</postal> </address> <netWorth>10</netWorth> </contact> <contact> <name>Gretchen Rivas</name> <phonetype="mobile">206-555-0163</phone> <address> <street1>123 Main St</street1> <city>Mercer Island</city> <state>WA</state> <postal>68042</postal> </address> <netWorth>11</netWorth> </contact> <contact> <name>Scott MacDonald</name> <phonetype="home">925-555-0134</phone> <phonetype="mobile">425-555-0177</phone> <address> <street1>345 Stewart St</street1> <city>Chatsworth</city> <state>CA</state> <postal>91746</postal> </address> <netWorth>500000</netWorth> </contact></contacts> Pavel JežekC# 3.0 and .NET 3.5
LINQ to XSD – Schema Aware programming • Without schema: publicstaticdouble GetTotalByZip(XElement root, int zip) {return ( from order in root.Elements("order"), item in order.Elements("item"),where(int) order.Element("address").Element("postal") == zipselect ((double) price * (int) qty) ).Sum(); } • With schema (1.0 downloadable from CodePlex): publicstaticdouble GetTotalByZip(Orders root, int zip) {return ( from order in root.OrderCollection, item in order.Itemswhere order.Address.Postal == zipselect (item.Price * item.Quantity) ).Sum(); } Pavel JežekC# 3.0 and .NET 3.5