views:

26

answers:

1

Hello All,
I have an IEnumerable<someClass>. I need to transform it into XML. There is a property called 'ZoneId'. I need to write some XML based on this property, then I need some decendent elements that provide data relevant to the ZoneId. I know I need some type of grouping. Here's what I have attempted thus far without much success. **inventory is an IEnumerable<someClass>. So I query inventory for unique zones. This works ok.

var zones = inventory.Select(c => new {
            ZoneID = c.ZoneId
            , ZoneName = c.ZoneName
            , Direction = c.Direction
        }).Distinct();

No I want to create xml based on zones and place. ***place is a property of 'someClass'.

        var xml = new XElement("MSG_StationInventoryList"
                               , new XElement("StationInventory"
                                              , zones.Select(station =>
                                                             new XElement("station-id", station.ZoneID)
                                                             , new XElement("station-name", station.ZoneName))));

This does not compile as "station" is out of scope when I try to add the "station-name" element. However is I remove the paren after 'ZoneId', station is in scope and I retreive the station-name. Only problem is the element is then a decendant of 'station-id'. This is not the desired output. They should be siblings. What am I doing wrong? Lastly after the "station-name" element, I will need another complex type which is a collection. Call it "places'. It will have child elements called "place". its data will come from the IEnumerable and I will only want "places" that have the "ZoneId" for the current zone. Can anyone point me in the right direction? Is it a mistake select distinct zones from the original IEnumerable? This object has all the data I need within it. I just need to make it heirarchical. Thanks for any pointers all.

Cheers,
Chris in San Diego

**Edit

var zones = inventory.Select(c => new {
            ZoneID = c.ZoneId
            , ZoneName = c.ZoneName
            , Direction = c.Direction
        }).Distinct();

        var xml = new XElement("MSG_StationInventoryList"
                               , zones.Select(station => new XElement("StationInventory"
                                     , new XElement("station-id", station.ZoneID)
                                     , new XElement("station-name", station.ZoneName)
                                     , new XElement("station-travel-direction", station.Direction)
                                     , new XElement("detector-list"
                                        , inventory.Where(p=>p.ZoneId == station.ZoneID).Select(plaza=> 
                                         new XElement("detector"
                                            , new XElement("detector-id", plaza.PlazaId)))))));

This ended up working.

+3  A: 

Try this:

zones.SelectMany(station => new object[]
{
    new XElement("station-id", station.ZoneID),
    new XElement("station-name", station.ZoneName),
    station.Places.Select(place => new XElement("place", place))
})

This creates an XML structure like this:

<MSG_StationInventoryList>
    <StationInventory>
        <station-id>Test1</station-id>
        <station-name>Test Station 1</station-name>
        <place>place1a</place>
        <place>place1b</place>
        <place>place1c</place>
        <station-id>Test2</station-id>
        <station-name>Test Station 2</station-name>
        <place>place2a</place>
        <place>place2b</place>
        <station-id>Test3</station-id>
        <station-name>Test Station 3</station-name>
        <place>place3a</place>
    </StationInventory>
</MSG_StationInventoryList>

Is that your intention?


If you can change the XML structure to something different, I'd suggest you make it like this:

<MSG_StationInventoryList>
    <StationInventory>
        <station>
            <station-id>Test1</station-id>
            <station-name>Test Station 1</station-name>
            <places>
                <place>place1a</place>
                <place>place1b</place>
                <place>place1c</place>
            </places>
        </station>
        <station>
            <station-id>Test2</station-id>
            <station-name>Test Station 2</station-name>
            <places>
                <place>place2a</place>
                <place>place2b</place>
            </places>
        </station>
        <station>
            <station-id>Test3</station-id>
            <station-name>Test Station 3</station-name>
            <places>
                <place>place3a</place>
            </places>
        </station>
    </StationInventory>
</MSG_StationInventoryList>

Then you can simply create an XElement for each station and place:

zones.Select(station => new XElement("station",
    new XElement("station-id", station.ZoneID),
    new XElement("station-name", station.ZoneName),
    new XElement("places",
        station.Places.Select(place => new XElement("place", place))))
dtb