smt
smt

Reputation: 267

LINQ - get element within element

I would like to extract information from a XML file (see below a specific portion of code):

<AssetsInterface>
  <Assets>
     <Asset>
       <Vehicle>
        <MaintenanceHistories>
          <MaintenanceHistory>
            <RepairDate>2014-07-02</RepairDate>
            <Mileage>30692</Mileage>
            <Dealer></Dealer>
            <Activities>
              <Activity>
                <Code></Code>
                <Description>Filtro de aceite</Description>
                <Amount>0</Amount>
              </Activity>
              <Activity>
                <Code></Code>
                <Description>Revisión 30000</Description>
                <Amount>0</Amount>
              </Activity>
            </Activities>
          </MaintenanceHistory>
          <MaintenanceHistory>
            <RepairDate>2015-03-27</RepairDate>
            <Mileage>63984</Mileage>
            <Dealer></Dealer>
            <Activities>
              <Activity>
                <Code></Code>
                <Description>Filtro de aceite</Description>
                <Amount>0</Amount>
              </Activity>
              <Activity>
                <Code></Code>
                <Description>Revisión 60000</Description>
                <Amount>0</Amount>
              </Activity>
              <Activity>
                <Code></Code>
                <Description>Escobillas</Description>
                <Amount>0</Amount>
              </Activity>
              <Activity>
                <Code></Code>
                <Description>Filtro de particulas</Description>
                <Amount>0</Amount>
              </Activity>
            </Activities>
          </MaintenanceHistory>
        </MaintenanceHistories>
      </Vehicle>
    </Asset>
  </Assets>
</AssetsInterface>

As you can see, it has multiple <MaintenanceHistory> with multiple <Activities> inside them. The output I am looking for is something like this:

2014-07-02 30692 Filtro de aceite
2014-07-02 30692 Revisión 30000
2015-03-27 63984 Filtro de aceite
2015-03-27 63984 Revisión 60000
2015-03-27 63984 Escobillas
2015-03-27 63984 Filtro de partículas

I have no problems to extract <RepairDate> and <Mileage>, even I extract the <Description>, but I cannot do it at once. This is my current poor code (after x1000 different tries...):

For Each desc As XElement In document.Descendants("Activity")
    carRepairDesc = desc.Element("Description")

    For Each options As XElement In document.Descendants("MaintenanceHistory")
        carRepairDate = options.Element("RepairDate").Value
        carRepairKMs = options.Element("Mileage").Value
    Next
    Console.WriteLine(carRepairDate & " " & carRepairKMs & "km " & carRepairDesc)
Next

The output of this code is a bit different:

2015-12-28 96833km Filtro de aceite
2015-12-28 96833km Revisión 30000
2015-12-28 96833km Filtro de aceite
2015-12-28 96833km Revisión 60000
2015-12-28 96833km Escobillas
2015-12-28 96833km Filtro de particulas

I wish you have any suggestion!

EDITED:

Thanks to @Hybridzz, here is the solution in VB.Net:

Dim document As XDocument = XDocument.Load("PATH TO XML")
Dim mHistory = From r In document.Descendants("MaintenanceHistory") Select New With {
    Key .RepairDate = r.Element("RepairDate").Value,
    Key .Mileage = r.Element("Mileage").Value,
    Key .ActivityDescs = r.Descendants("Activity").[Select](Function(x) x.Element("Description").Value)
     }

For Each r In mHistory
    For Each activityDesc In r.ActivityDescs
        Console.WriteLine(String.Format("{0} {1} {2} {3}", r.RepairDate, r.Mileage, activityDesc, Environment.NewLine))

    Next
Next

Upvotes: 1

Views: 165

Answers (1)

Sin
Sin

Reputation: 1864

This is a c# version, but you will be able to change to VB .net

  XDocument document = XDocument.Load(@"PATH TO XML");

        var mHistory = from r in document.Descendants("MaintenanceHistory")
                    select new
                    {
                        RepairDate = r.Element("RepairDate").Value,
                        Mileage = r.Element("Mileage").Value,
                        ActivityDescs = r.Descendants("Activity").Select(x => x.Element("Description").Value)
                    };

        foreach (var r in mHistory)
        {
            foreach (var activityDesc in r.ActivityDescs)
            {
                Console.WriteLine(string.Format("{0} {1} {2} {3}", r.RepairDate, r.Mileage, activity,  Environment.NewLine));
            }

        }  

and output is

2014-07-02 30692 Filtro de aceite 
2014-07-02 30692 Revisión 30000 
2015-03-27 63984 Filtro de aceite 
2015-03-27 63984 Revisión 60000 
2015-03-27 63984 Escobillas 
2015-03-27 63984 Filtro de particulas 

Upvotes: 3

Related Questions