Entwickler-Ecke
IO, XML und Registry - Xml mit Linq lesen: Null Exception :(
Schafschaf - Di 31.03.15 11:50
Titel: Xml mit Linq lesen: Null Exception :(
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)
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.
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 { 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:
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 - 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 [
http://chodounsky.net/2013/10/23/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.
Schafschaf - Mi 01.04.15 12:08
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:
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 - 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;
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() ?? "") :"" } |
Schafschaf - Mi 01.04.15 15:55
Und wieder mal was dazu gelernt. Danke ( ͡° ͜ʖ ͡°)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!