Autor Beitrag
Schafschaf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Di 31.03.15 11:50 
Hallo Leute,

ich hab mal wieder ein Problem, wo ich nicht weiterkomme :(
Ich möchte ein paar Daten aus einer Xml Datei lesen und sie in ein Objekt schreiben um sie zur späteren Verwendung in ein anderes Format zu schreiben.
So sieht die Xml-Datei aus. Wobei es viele <Order> gibt und die Elemente voneinander abweichen (z.B. bei Firmenbestellungen gibt es noch <Company>, die tauchen meistens gar nicht auf)


ausblenden volle Höhe XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
<?xml version='1.0' encoding='utf-8'?>
<Orders>
  <Shop>
    <GUID>datenschutz</GUID>
  </Shop>
  <Order>
    <OrderNumber>datenschutz</OrderNumber>
    <CustomerNumber>datenschutz</CustomerNumber>
    <Currency>datenschutz</Currency>
    <Language>de</Language>
    <Locale>de_DE</Locale>
    <TaxArea>EU</TaxArea>
    <TaxModel>gross</TaxModel>
    <GrandTotal>datenschutz</GrandTotal>
    <TotalBeforeTax>datenschutz</TotalBeforeTax>
    <TotalTax>datenschutz</TotalTax>
    <Addresses>
      <BillingAddress>
        <FirstName>datenschutz</FirstName>
        <LastName>datenschutz</LastName>
        <Street>datenschutz</Street>
        <Zipcode>datenschutz</Zipcode>
        <State>datenschutz</State>
        <City>datenschutz</City>
        <EMail>datenschutz</EMail>
        <Phone>datenschutz</Phone>
        <Country>DE</Country>
      </BillingAddress>
      <ShippingAddress>
        <FirstName>datenschutz</FirstName>
        <LastName>datenschutz</LastName>
        <Street>datenschutz</Street>
        <Zipcode>datenschutz</Zipcode>
        <State>datenschutz</State>
        <City>datenschutz</City>
        <Phone>datenschutz</Phone>
        <Country>DE</Country>
      </ShippingAddress>
    </Addresses>
    ... ... ... 
  </Order>
  <Order>
     ... ... ...
  </Order>


Das Lesen der Daten sollte mit einer Linq-Abfrage erfolgen.
Vorher hatte ich First(), da kam immer "Die Sequenz enthält keine Elemente". Ist ja klar, First erzwingt ja quasi dass was kommt.
Deshalb habe ich jetzt überall FirstOrDefault(). Jetzt kommt "Der Objektverweis wurde nicht auf eine Objektinstatz festgelegt".
Nicht bei der Abfrage selbst, immer nur wenn ich versuche mit dem Objekt "Orders" zu arbeiten, nämlich "Orders" zu durchlaufen und dessen Werte in die Liste ins "Shipment" Objekt einzutragen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
XDocument xdoc = XDocument.Load("datei.xml");
                       
            List<Shipment> shipments = new List<Shipment>();

            var Orders = from Order in xdoc.Descendants("Order")
                         select new
                         {
                             //das sind nur ein paar als Beispiel
                             OrderNumber = Order.Descendants("OrderNumber").FirstOrDefault().Value,
                             stomerNumber = Order.Descendants("CustomerNumber").FirstOrDefault().Value, 
                             BillingAddressPhone = Order.Descendants("Addresses").Descendants("BillingAddress").FirstOrDefault().Descendants("Phone").FirstOrDefault().Value,
                             BillingAddressCountry = Order.Descendants("Addresses").Descendants("BillingAddress").FirstOrDefault().Descendants("Country").FirstOrDefault().Value,
                             ShippingAddressFirstName = Order.Descendants("Addresses").FirstOrDefault().Descendants("ShippingAddress").FirstOrDefault().Descendants("FirstName").FirstOrDefault().Value,
                         }


Selbst eine Abfrage ob es Null ist, bringt nichts:

ausblenden C#-Quelltext
1:
BillingAddressPhone = Order.Descendants("Addresses").Descendants("BillingAddress").FirstOrDefault().Descendants("Phone").FirstOrDefault() != null ? BillingAddressPhone = Order.Descendants("Addresses").Descendants("BillingAddress").FirstOrDefault().Descendants("Phone").FirstOrDefault().Value : "",					


Ich denke es ist mal wieder was ganz Doofes, Einfaches..

Freue mich um jeden Rat :)

LG Schafschaf
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 31.03.15 15:51 
Hallo,

dein Code ist ein bißchen zu komplex (besonders bzgl. der häufigen Aufrufe von Descendants).

Außerdem scheint dir die Descendants-Methode nicht ganz klar zu sein (oder?): Descendants vs. Elements in Linq to XML

Und bzgl. FirstOrDefault: im Gegensatz zu First liefert diese Methode keine Exception, sondern null, wenn kein passendes Element gefunden wurde. Dies bedeutet aber nicht, daß du dann einfach auf untergeordnete Eigenschaften (wie Value) zugreifen darfst (ohne explizit auf null zu testen).

Statt der einen langen Zeile mit x Methodenaufrufen solltest du also jede Methode einzeln aufrufen und die Rückgabewerte überprüfen!

Außerdem solltest du mittels des Debuggers die Fehler schnell selber finden.

Für diesen Beitrag haben gedankt: Schafschaf
Schafschaf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 01.04.15 12:08 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:


Außerdem scheint dir die Descendants-Methode nicht ganz klar zu sein (oder?): Descendants vs. Elements in Linq to XML

Und bzgl. FirstOrDefault: im Gegensatz zu First liefert diese Methode keine Exception, sondern null, wenn kein passendes Element gefunden wurde. Dies bedeutet aber nicht, daß du dann einfach auf untergeordnete Eigenschaften (wie Value) zugreifen darfst (ohne explizit auf null zu testen).


Danke, das hat mir geholfen, jetzt funktioniert es!
Also vom Prinzip her habe ich es verstanden, bevor ich z.B. irgendwo in ShippingAddress was hole/prüfe, schaue ich ob es ShippingAddress überhaupt gibt und mache erst dann weiter.
Ich habe es jetzt so gelöst:

ausblenden C#-Quelltext
1:
 ShippingAddressFirstName = Order.Elements("Addresses").FirstOrDefault().Elements("ShippingAddress").FirstOrDefault() != null ? Order.Elements("Addresses").FirstOrDefault().Elements("ShippingAddress").FirstOrDefault().Elements("FirstName").FirstOrDefault() != null ?   Order.Elements("Addresses").FirstOrDefault().Elements("ShippingAddress").FirstOrDefault().Elements("FirstName").FirstOrDefault().Value : "" :""					


Sieht syntaktisch zwar scheußlich aus, aber in dem select-Block kann ich ja keine if-Blöcke benutzen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 01.04.15 12:16 
man kann aber im Ausdruck mit let Dinge vordefinieren und dann auch das ganze mit dem ?? Operator kürzen. Etwa;

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
var orders = from Order in xdoc.Descendants("Order")
             let shippingAddress = Order.Elements("Addresses").First().Elements("ShippingAddress").FirstOrDefault()
             select new 
             {
                 ...
                 ShippingAddressFirstName = shippingAddress != null ? (shippingAddress.Elements("FirstName").FirstOrDefault() ?? "") :""          
             }

Für diesen Beitrag haben gedankt: Schafschaf
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 01.04.15 12:22 
Hallo

mittels des LINQ Schlüsselworts let läßt sich der Ausdruck aber sehr vereinfachen.

Edit: Code entfernt, da Ralf ja schon schneller gepostet hat ;-)
Schafschaf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 01.04.15 15:55 
Und wieder mal was dazu gelernt. Danke ( ͡° ͜ʖ ͡°)