Tuesday, February 10, 2009

Xml to Html Using LINQ

Here’s something I just worked up to convert Xml to Html using Linq. My goal was to produce output that looks like:

goal

The xml string I have to work with is:

<Layers request='GetLayerFieldInfo' count='9' message=''>
    <layer name='AirportOverlayDistrict'>
        <fields count='1'>
            <field name='id' type='string' />
        </fields>
    </layer>
    <layer name='CarpenterHistoricDistrict'>
        <fields count='2'>
            <field name='name' type='string' />
            <field name='calcac' type='decimal' />
        </fields>
    </layer>
    <layer name='GreenLevelHistoricDistrict'>
        <fields count='2'>
            <field name='name' type='string' />
            <field name='calcac' type='decimal' />
        </fields>
    </layer>
    <layer name='ConservResOverlayDistrict'>
        <fields count='2'>
            <field name='type' type='string' />
            <field name='acres' type='decimal' />
        </fields>
    </layer>
    <layer name='NWAreaPlan'>
        <fields count='1'>
            <field name='name' type='string' />
        </fields>
    </layer>
    <layer name='SEAreaPlan'>
        <fields count='2'>
            <field name='name' type='string' />
            <field name='calcac' type='decimal' />

    </layer>
    <layer name='SWAreaPlan'>
        <fields count='2'><field name='name' type='string' />
            <field name='calcac' type='decimal' />
        </fields>
    </layer>
    <layer name='WanutStreetCorridorPlan'>
        <fields count='2'>
            <field name='name' type='string' />
            <field name='calcac' type='decimal' />
        </fields>
    </layer>
    <layer name='TownCenterAreaPlan'>
        <fields count='2'>
            <field name='name' type='string' />
            <field name='calcac' type='decimal' />
        </fields>
    </layer>
</Layers>

Now, I know there are a ton of different ways to accomplish this. I initially used a brute force approach and generated the html by looping through the xml document and writing the individual lines of html. I wanted to use Linq, so I started looking around to see how it can be done.

Nothing matched up very well because of the “real” data is stored as attributes instead of elements. But with some trial and error, I came up with the following Linq statement to produce what I wanted:

private string XmlToHtml(string value)
{
    XElement layersXml = XElement.Parse(value);

    XElement html =
    new XElement("div", new XElement("div", new XAttribute("class", "info"), "This request has returned field information for ", layersXml.Attribute("count").Value, " layer tables."),
        from layer in layersXml.Descendants("layer")
        select new XElement("div",
            new XAttribute("class", "layerinfo"),
            new XElement("h3", new XAttribute("class", "layername"), (string)layer.Attribute("name")),
            new XElement("div", new XAttribute("class", "fields"),
                from field in layer.Elements("fields").Descendants("field")
                select new XElement("div",
                    new XElement("span", new XAttribute("class", "fnametxt"), "Field Name: "),
                    new XElement("span", new XAttribute("class", "fieldname"),(string)field.Attribute("name")),
                    new XElement("span", new XAttribute("class", "typetxt"), "Type: "),
                    new XElement("span", new XAttribute("class", "typename"), (string)field.Attribute("type"))))
        )
    );
    return html.ToString();

}

This is not the most elegant code as you still need to know a lot about the structure and names contained in the xml. It really is kind of cool the way you can tie the code together though.

No comments: