Laden...

XML Datei in CSV wandeln mit LINQ gibt NullReference-Exception

Erstellt von RevangeXX vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.702 Views
R
RevangeXX Themenstarter:in
5 Beiträge seit 2018
vor 6 Jahren
XML Datei in CSV wandeln mit LINQ gibt NullReference-Exception

Hallo,

ich möchte eine XML Datei in ein CSV Format wandeln.

Leider bekomme ich den Code nicht ganz hin.

Ich bekomme eine Fehlermeldung:> Fehlermeldung:

Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt

XML hat folgende Struktur:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TimeKeepingEntries xmlns="">
    <entry>
        <staffNumber>22</staffNumber>
        <salaryTypeNumber>200</salaryTypeNumber>
        <businessProcess>
            <processNumber>170023</processNumber>
            <processType>PROJECT</processType>
        </businessProcess>
        <workingPeriod>
            <period>4.0</period>
            <periodUnit>HOURS</periodUnit>
            <beginDate>2018-01-02Z</beginDate>
            <endDate>2018-01-02Z</endDate>
            <timespan>
                <beginTime>08:00:00Z</beginTime>
                <endTime>12:00:00Z</endTime>
            </timespan>
        </workingPeriod>
        <costUnit>170023</costUnit>
    </entry>
    <entry>
        <staffNumber>22</staffNumber>
        <salaryTypeNumber>210</salaryTypeNumber>
		<businessProcess>
            <processNumber>170023</processNumber>
            <processType>PROJECT</processType>
        </businessProcess>
        <workingPeriod>
            <period>10.0</period>
            <periodUnit>HOURS</periodUnit>
            <beginDate>2018-01-01Z</beginDate>
            <endDate>2018-01-01Z</endDate>
            <timespan>
                <beginTime>08:00:00Z</beginTime>
                <endTime>16:00:00Z</endTime>
            </timespan>
        </workingPeriod>
    </entry>
</TimeKeepingEntries>

Code:


static void Main(string[] args)
        {
            XElement custOrd = XElement.Load("stunden.xml");
            string csv =
                (from el in custOrd.Element("TimeKeepingEntries").Elements("entry")
                 select
         String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}",
             (string)el.Element("staffNumber"),
             (string)el.Element("salaryTypeNumber"),
             (string)el.Element("businessProcess").Element("processNumber"),
             (string)el.Element("businessProcess").Element("processType"),
             (string)el.Element("workingPeriod").Element("period"),
             (string)el.Element("workingPeriod").Element("periodUnit"),
             (string)el.Element("workingPeriod").Element("beginDate"),
             (string)el.Element("workingPeriod").Element("endDate"),
             (string)el.Element("workingPeriod").Element("timespan").Element("beginTime"),
             (string)el.Element("workingPeriod").Element("timespan").Element("endTime"),
             (string)el.Element("costUnit"),
             Environment.NewLine
         )
                )
                .Aggregate(
                    new StringBuilder(),
                    (sb, s) => sb.Append(s),
                    sb => sb.ToString()
                );
            Console.WriteLine(csv);
        }

16.806 Beiträge seit 2008
vor 6 Jahren

Dann ist etwas null.

Siehe [FAQ] NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt und [Artikel] Debugger: Wie verwende ich den von Visual Studio?
Damit findest Du den Fehler selbst; vermutlich wird ein Element nicht gefunden oder sowas.

Die korrekte Weise einen Wert zu lesen ist das Value-Property abzufragen und nicht auf einen String zu casten.

R
RevangeXX Themenstarter:in
5 Beiträge seit 2018
vor 6 Jahren

Hallo,

danke für die Antwort.

Danach hab ich schon gesucht. Ich finde aber den Fehler nicht. Bin auch noch Anfänger auf diesem Gebiet.

C
2.121 Beiträge seit 2010
vor 6 Jahren

Du bist Anfänger im Debuggen, wirfst aber gleich wilde Linq Statements in deinen Code die du dann nicht mehr unter Kontrolle hast? Ich würde einen Schritt nach dem anderen machen.

5 Beiträge seit 2018
vor 6 Jahren
 custOrd.Element("TimeKeepingEntries")

liefert dir

NULL 

zurück.

custOrd.Elements("entry")

wäre korrekt.

Edit:
In deiner XML Struktur ist "TimeKeepingEntries" der Name und "entry" die einzelnen Elemente.
Durch das Debuggen hättest du festgestellt das der Aufruf custOrd.Element("TimeKeepingEntries") NULL zurückliefert und entsprechend der Rest dann auf eine NullReference läuft.

Wenn du dir den Aufruf

 XElement custOrd = XElement.Load("stunden.xml");

Im Debugger / Watch anschaust wirst du feststellen das custOrd.Name == "TimeKeepingEntries" ist.

Developers, Developers, Developers, Developers,
Developers, Developers, Developers, Developers,
Developers, Developers, Developers, Developers ...

:evil:

T
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

mal abgesehen davon ist die Schreibweise eher gefährlich der nächsten 'null'-Exception nahe.

Sollte mal durch irgendwelche Umstände ein Element fehlen, dann knallts wieder.

Dabei spielt auch immer die Rolle, welche Infos sind pflicht und welche nur optional, jenachdem sollte man Fehlerbehandlungen einbauen oder einfach vorher auf 'null' prüfen...

Grüße

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

5.941 Beiträge seit 2005
vor 6 Jahren

Hallo RevangeXX

Ich würde auch schauen, dass du die Doppeltungen der Keys, bspw. von "workingPeriod" loswirst.
Du lädst dieses Element einmal in eine Variable und kannst dann davon Untereelemente abfragen.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

3.003 Beiträge seit 2006
vor 6 Jahren

Da's noch keiner erwähnt hat:

Null Propagation

i.e.:


el?.Element("businessProcess")?.Element("processNumber")

Bei einem string.format ist zudem der cast auf string nicht nur überflüssig, sondern, da's ein "harter" cast ist, auch noch gefährlich. Dazu wäre es ein guter Gedanke, string interpolation zu nutzen.

Zu guter Letzt kann man sich angewöhnen, zu parsendes XML immer zu validieren, bevor man es parst. Entweder das, oder man prüft beim Parsen, ob alle benötigten Elemente da sind (und wenn man das macht, muss an sich fragen lassen, wieso man überhaupt XML nutzt. Validierung kommt quasi kostenlos mit XML...).

Oder man lässt den ganzen händischen Kram und serialisiert/deserialisiert. Ist auch schneller und fehlerfreier geschrieben.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)