Analyze Linq hierarchical to XML

advertisements

I am trying to parse this data:

    <Product>
    <ProductName>Climate Guard</ProductName>
    <Tag>ClimateGuard</Tag>
    <SupportPage>~/Support/ClimateGuard.aspx</SupportPage>
    <ProductPage>~/Products/ClimateGuard.aspx</ProductPage>
    <ProductCategories>
        <ProductCategory>Climate Guard</ProductCategory>
        <PartNumbers>
            <PartNumber Primary="true">CLIMATE GUARD</PartNumber>
            <PartNumber>CLIMATEGUARD LT</PartNumber>
            <PartNumber>CLIMATE GUARD STARTER KIT</PartNumber>
            <PartNumber>SENSOR MODULE</PartNumber>
            <PartNumber>SWCH INP MODULE</PartNumber>
            <PartNumber>TEMP SENSOR</PartNumber>
            <PartNumber>HUMIDITY SENSOR</PartNumber>
            <PartNumber>DOOR CONTACT</PartNumber>
            <PartNumber>MOTION SENSOR</PartNumber>
            <PartNumber>FLOOD DETECTOR</PartNumber>
            <PartNumber>SMOKE DETECTOR</PartNumber>
            <PartNumber>TILT SENSOR</PartNumber>
            <PartNumber>SENSOR CABLE</PartNumber>
            <PartNumber>PWR INP CABLE</PartNumber>
            <PartNumber>100FT 2-WIRE</PartNumber>
            <PartNumber>RJ25 COUPLER</PartNumber>
        </PartNumbers>
    </ProductCategories>
    <Downloads>
        <Download>
            <Version>1.0.27</Version>
            <Url>~/Files/Downloads/ClimateGuard_Firmware_1_0_27.bin</Url>
            <Comment>Firmware</Comment>
        </Download>
        <Download>
            <Version>1.0.6</Version>
            <Url>~/Files/Downloads/ClimateGuard_BuiltInModule_1_0_6.bin</Url>
            <Comment>Built-in Module</Comment>
        </Download>
        <Download>
            <Version>1.0.2</Version>
            <Url>~/Files/Downloads/ClimateGuard_SensorModule_1_0_2.bin</Url>
            <Comment>Sensor Module</Comment>
        </Download>
        <Download>
            <Version>1.0.0</Version>
            <Url>~/Files/Downloads/ClimateGuard_SwitchInputModule_1_0_0.bin</Url>
            <Comment>Switch Input Module</Comment>
        </Download>
    </Downloads>
</Product>

I am trying to get a List of part numbers, however, only the first appears:

Product Category Climate Guard Part Number Climate Guard

What is wrong with my part numbers code:

public List<Products> GetProducts()
{
    XElement myElement = XElement.Load(HttpContext.Current.Server.MapPath("~/App_Data/products.xml"));
    var query = from a in myElement.Elements("Product")
                select new Products
                {
                    ProductName = a.Element("ProductName").Value,
                    Tag = a.Element("Tag").Value,
                    SupportPage = a.Element("SupportPage").Value,
                    ProductPage = a.Element("ProductPage").Value,
                    ProductCategories = from b in a.Elements("ProductCategories")
                                        select new ProductCategories
                                        {
                                            ProductCategory = b.Element("ProductCategory").Value,
                                            //PartNumbers = GetPartNumbers(myElement.Elements("Product").Elements("ProductCategories").Elements("PartNumbers").Elements("PartNumber"))
                                            PartNumbers = from c in b.Elements("PartNumbers")
                                                          select new PartNumbers
                                                          {
                                                               PartNumber = c.Element("PartNumber").Value
                                                          }
                                        },
                    Downloads = from bb in a.Elements("Downloads").Elements("Download")
                                select new Downloads
                                {
                                    Comment = bb.Element("Comment").Value,
                                    Url = bb.Element("Url").Value,
                                    Version = bb.Element("Version").Value
                                },
                };

    return query.ToList();
}

All of the types (ProductName, Tag, etc.) are strings. PartNumbers is an IEnumerable.


Currently instead of getting collection of PartNumber element values, you are getting only element for their parent PartNumbers with value of first PartNumber child inside. If you want to have PartNumbers class instead of simple list of string values, then it should look like:

public class PartNumbers
{
    // list instead of single value
    public List<string> Numbers { get; set; }
}

And it should be parsed this way:

PartNumbers = new PartNumbers {
       Numbers = b.Element("PartNumbers").Elements()
                  .Select(c => (string)c).ToList()
       }

BTW why are you choosing so strange range variable names (b for ProductCategories elements, a for products, etc)? Also you can use simple List<string> to store part numbers (without creating class for that):

PartNumbers = b.Element("PartNumbers").Elements().Select(c => (string)c).ToList()