[C# LINQ] selecteren query - invalid xml

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Gerrit88
  • Registratie: Maart 2007
  • Laatst online: 08:40
Ik heb een stukje code geschreven waarmee ik een xml export inlees. Het probleem is dat deze export geen valid xml is. Aan dit feit kan niets veranderd worden, ik zal het probleem dus in mijn code moeten ondervangen.

Een xml element ziet er als volgt uit
XML:
1
2
3
4
5
6
7
8
9
10
11
12
<Medewerker_koppeling_AD>
    <EmId>1234</EmId>
    <Voornaam>Pietje</Voornaam>
    <Voorletters>P.</Voorletters>
    <Achternaam>Puk</Achternaam>
    <Status_dienstverband_code>I</Status_dienstverband_code>
    <BiMo>Postbode</BiMo>
    <BiYe>TNT</BiYe>
    <Vestiging>Keteldorp</Vestiging>
    <Geboortedatum>1950-01-01</Geboortedatum>
    <Geslacht>Man</Geslacht>
</Medewerker_koppeling_AD>


Als een veld niet is ingevuld in het pakket dat de export maakt ontbreekt dit veld ook in de export, ik mis dus een element in mijn xml!

Mijn code om de xml te lezen ziet er als volgt uit:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   private IEnumerable<User> getAllEmployees() {
            try {
                IEnumerable<User> userList =
                    from c in xmlDoc.Descendants("Medewerker_koppeling_AD")
                    select new User() {
                        EmployeeNumber = int.Parse(c.Element("EmId").Value),
                        FirstName = c.Element("Voornaam").Value,
                        Initials = c.Element("Voorletters").Value,
                        Name = c.Element("Achternaam").Value,
                    };
                return userList;
            } catch (Exception e) {
                throw new xmlDocumentParseException("Error during parsing xmlDocument", e);
            }
        }
    }


Kan ik op de een of andere manier in de linq query controleren of deze bestaat en als dit niet zo is een standaard waarde gebruiken? Uiteraard kan ik gewoon 'traditioneel' door de xml heen lopen maar ik wil graag linq gebruiken omdat het zo snel is.

Ik denk aan iets als (pseudo code):
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   private IEnumerable<User> getAllEmployees() {
            try {
                IEnumerable<User> userList =
                    from c in xmlDoc.Descendants("Medewerker_koppeling_AD")
                    select new User() {
                        if(exist(c.Element("EmId"))
                            EmployeeNumber = int.Parse(c.Element("EmId").Value),
                        else
                            EmployeeNumber = 0,
                        FirstName = c.Element("Voornaam").Value,
                        Initials = c.Element("Voorletters").Value,
                        Name = c.Element("Achternaam").Value,
                    };
                return userList;
            } catch (Exception e) {
                throw new xmlDocumentParseException("Error during parsing xmlDocument", e);
            }
        }
    }


Hopelijk weet iemand een goede oplossing!

Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Kan je niet een functie schijven alzo:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
public T FetchDescendant<T>(string elementName, XElement element)
{
   XElement el = element.Element(elementName);
   if(null != el)
   {
      return (T)element.Value
   }
   else
   {
      return default(T);
   }
}

En die dan gebruiken om je element te fetchen.

XElement.Element returned null als het element niet gevonden kan worden.

Helaas zit je dan nog met het probleem als je een integer verwacht.

Dus je refactored naar dit:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
// zet dit in een static class!!!!
public static T FetchDescendant<T>(this XElement element, string elementName)
{
   XElement drilledDownElement = element.Element(elementName);
   if(null != drilledDownElement )
   {
      return (T)Convert.ChangeType(drilledDownElement.Value, typeof(T));
   }
   else
   {
      return default(T);
   }
}

En in jouw eerste voorbeeld geeft dit dit:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   private IEnumerable<User> getAllEmployees() {
            try {
                IEnumerable<User> userList =
                    from c in xmlDoc.Descendants("Medewerker_koppeling_AD")
                    select new User() {
                        EmployeeNumber = c.FetchDescendant<int>("EmId"),
                        FirstName = c.FetchDescendant<string>("Voornaam"),
                        Initials = c.FetchDescendant<string>("Voorletters"),
                        Name = c.FetchDescendant<string>("Achternaam"),
                    };
                return userList;
            } catch (Exception e) {
                throw new xmlDocumentParseException("Error during parsing xmlDocument", e);
            }
        }
    }

[ Voor 100% gewijzigd door Snake op 17-02-2010 14:55 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Gerrit88
  • Registratie: Maart 2007
  • Laatst online: 08:40
Snake, super bedankt! Ben even aan het puzzelen geweest met je oplossing en het is gelukt. Je voorstel werkt perfect!

De functie definitie die je gebruikt ken ik niet.
C#:
1
public T FetchDescendant<T>(this XElement element, string elementName) 

waar komt 'this XElement element' nou precies vandaan?

In ieder geval super bedankt!

Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Gerrit88 schreef op woensdag 17 februari 2010 @ 14:54:
Snake, super bedankt! Ben even aan het puzzelen geweest met je oplossing en het is gelukt. Je voorstel werkt perfect!

De functie definitie die je gebruikt ken ik niet.
C#:
1
public T FetchDescendant<T>(this XElement element, string elementName) 

waar komt 'this XElement element' nou precies vandaan?

In ieder geval super bedankt!
Dat is een extension method. (ik heb mijn post geupdated, die methode moet static!!!!)

Pak dat je die methode in een class plaatst:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// hence static
public static class ExtensionMethods
{
   // zet dit in een static class!!!!
   public static T FetchDescendant<T>(this XElement element, string elementName)
   {
      XElement drilledDownElement = element.Element(elementName);
      if(null != drilledDownElement )
      {
         return (T)Convert.ChangeType(drilledDownElement.Value, typeof(T));
      }
      else
      {
         return default(T);
      }
   }
}


jouw c in

C#:
1
2
3
4
5
6
7
                 from c in xmlDoc.Descendants("Medewerker_koppeling_AD")
                    select new User() {
                        EmployeeNumber = c.FetchDescendant<int>("EmId"),
                        FirstName = c.FetchDescendant<string>("Voornaam"),
                        Initials = c.FetchDescendant<string>("Voorletters"),
                        Name = c.FetchDescendant<string>("Achternaam"),
                    };  

is van het type XElement.

Door in mijn methode 'this' voor de eerste parameter te zetten wordt dat een extension method die werkt op XElement.

Door de compiler wordt dit dan vertaald naar:
C#:
1
2
3
4
5
6
7
from c in xmlDoc.Descendants("Medewerker_koppeling_AD")
                    select new User() {
                        EmployeeNumber = ExtensionMethods.FetchDescendant<int>(c, "EmId"),
                        FirstName = ExtensionMethods.FetchDescendant<string>(c, "Voornaam"),
                        Initials = ExtensionMethods.FetchDescendant<string>(c, "Voorletters"),
                        Name = ExtensionMethods.FetchDescendant<string>(c, "Achternaam"),
                    }; 

Lees ook even dit.

Zo, dit moet je verder helpen ;)

[ Voor 10% gewijzigd door Snake op 17-02-2010 15:02 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Gerrit88
  • Registratie: Maart 2007
  • Laatst online: 08:40
Dat het static moet zijn had ik inderdaad door :D.

Bedankt voor de duidelijke uitleg. Weer wat geleerd! De documentatie is zeker interessant om te lezen!