Creating XML Trees

From IronPython Cookbook

Starting with .NET Framework 3.5, LINQ to XML introduced a new and lightweight object model for creating and manipulating XML trees. The object model resides in the System.Linq.Xml namesapce.

Compared to the XML DOM API residing in the System.Xml namespace, LINQ to XML takes a new approach to creating XML trees, dubbed as functinal construction. For a comparison, see "LINQ to XML Programming Approaches Overview." Functional construction is discussed in more detail under, "In-Memory XML Tree Modification vs. Functional Construction (LINQ to XML)." In short, however, functional construction means that a tree of XML nodes is created through chaining calls to constructors. There is also some magic created through implicit conversion operators on certain classes. Consider the following C# example from the documentation:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"), 
            new XElement("Phone", "206-555-0144"),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );

Translating this to IronPython is farily straightforward, except for the element names. None of the XElement constructors accepts a string as the first argumet. In fact, all constructors only accept XName objects. The reason the above still works is because there is exists an implicit conversion from string to XName. In IronPython, the XName has to be created explicitly via the XName.Get factory method. Here's how the same example would translate into IronPython

contacts = XElement(XName.Get("Contacts"),
    XElement(XName.Get("Contact"),
        XElement(XName.Get("Name"), "Patrick Hines"),
        XElement(XName.Get("Phone"), "206-555-0144"),
        XElement(XName.Get("Address"),
            XElement(XName.Get("Street1"), "123 Main St"),
            XElement(XName.Get("City"), "Mercer Island"),
            XElement(XName.Get("State"), "WA"),
            XElement(XName.Get("Postal"), "68042")
        )
    )
)

Note that to try this out in the IronPython interpreter, you need to single logical line of chained construction differently. Placing commas at the end, for example, causes syntax errors. The workaround is to place commas on the next line as shown here:

IronPython console: IronPython 2.0A6 (2.0.11102.00) on .NET 2.0.50727.1433
Copyright (c) Microsoft Corporation. All rights reserved.
>>> import clr
>>> clr.AddReference('System.Xml.Linq')
>>> from System.Xml.Linq import *
>>> contacts = XElement(XName.Get("Contacts")
...   , XElement(XName.Get("Contact")
...       , XElement(XName.Get("Name"), "Patrick Hines")
...       , XElement(XName.Get("Phone"), "206-555-0144")
...       , XElement(XName.Get("Address")
...           , XElement(XName.Get("Street1"), "123 Main St")
...           , XElement(XName.Get("City"), "Mercer Island")
...           , XElement(XName.Get("State"), "WA")
...           , XElement(XName.Get("Postal"), "68042")
...         )
...     )
... )
>>> print contacts
<Contacts>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone>206-555-0144</Phone>
    <Address>
      <Street1>123 Main St</Street1>
      <City>Mercer Island</City>
      <State>WA</State>
      <Postal>68042</Postal>
    </Address>
  </Contact>
</Contacts>

Note also that XElement objects can be directly printed because the ToString implementation (actually that of XNode, of which XElement is a subclass) is overridden to produce indented XML 1.0 representation.


Back to Contents.

TOOLBOX
LANGUAGES