I am a student trying to learn how to code. I have been assigned the task of loading data from a complex XML file into a list. I've thought about how to approach this for quite a while, and this is the best I came up with. However, it feels wrong. What am I missing? How would a real developer handle this?
private void loadFromFile(string filename)//load all data from file to list
{
try
{
XDocument doc = XDocument.Load(filename);
XElement sessioniGiornaliere = doc.Root.Element("SessioniGiornaliere");
if (sessioniGiornaliere != null)
{
foreach (XElement sessioneGiornaliera in sessioniGiornaliere.Elements("SessioneGiornaliera"))//sessione giornaliera is closed anytime there is there is a closingSession
{
List<CommercialDocument> documentList = new List<CommercialDocument>();//list of documents (containing type, es:"Vendita" ant totImport amount)
foreach (XElement type in sessioneGiornaliera.Elements("DocumentiEmessi").Elements("DocumentoCommerciale"))//scrolling trough every
{
List<Line> lineList = new List<Line>();
List<SubLine> subLines = new List<SubLine>(); //document before arriving at the Closure
string documentType = type.Elements().FirstOrDefault()?.Name.LocalName;
double amount = Convert.ToDouble(type.Element(documentType).Element("ImportoTotale")?.Value) / 100;
int numDocument = Convert.ToInt32(type.Element(documentType).Element("NumeroDocumento")?.Value);
foreach (XElement l in type.Elements("Vendita").Elements("Dettaglio").Elements("RigaGenerica"))//loading every doughter of riga generica
{
if(l.Element("Riga")!=null)//if the doughter is riga it loads everithing in the LineList
{
double equivalent = Convert.ToDouble(l.Element("Riga").Element("Elemento").Element("Importo")?.Value);
string description = l.Element("Riga").Element("Elemento").Element("Descrizione")?.Value;
int qt = Convert.ToInt32(l.Element("Riga").Element("Elemento").Element("Quantita")?.Value);
double unitPrice = Convert.ToDouble(l.Element("Riga").Element("Elemento").Element("PrezzoUnitario")?.Value);
double iva = 0;//set to 0 in case instead of IVA we have Natura (wich is the same as 0)
if(l.Element("Riga").Element("Elemento").Element("IVA")!=null)
iva = Convert.ToDouble(l.Element("Riga").Element("Elemento").Element("IVA").Element("AliquotaIVA")?.Value);
if (l.Element("Riga").Element("ModificatoreElemento")!=null)//if it has a modifier it aplies it before loading to the list
{
if (l.Element("Riga").Element("ModificatoreElemento").Element("Segno")?.Value == "-")
equivalent -= Convert.ToDouble(l.Element("Riga").Element("ModificatoreElemento").Element("Importo")?.Value);
else
equivalent += Convert.ToDouble(l.Element("Riga").Element("ModificatoreElemento").Element("Importo")?.Value);
}
Line line = new Line(equivalent/100,description, qt,unitPrice/100, iva / 100);//divifing by 100 because Convert.TODouble doesen't work somehow
lineList.Add(line);
}else if(l.Element("RigaSubtotale")!=null)//if it is Riga subTot it loads to a different list of the document because it has different preperties
{
double subTot = Convert.ToDouble(l.Element("RigaSubtotale").Element("SubTotale")?.Value);//cheks twice because it might have a subTot and not everything else
if (l.Element("RigaSubtotale").Element("ModificatoreSubTotale") != null)
{
double Import = Convert.ToDouble(l.Element("RigaSubtotale").Element("ModificatoreSubTotale").Element("Importi")?.Value);
string sign = Convert.ToString(l.Element("RigaSubtotale").Element("ModificatoreSubTotale").Element("Segno")?.Value);
string description = Convert.ToString(l.Element("RigaSubtotale").Element("ModificatoreSubTotale").Element("Descrizione")?.Value);
SubLine subLine = new SubLine(subTot/100, Import/100, sign, description);
subLines.Add(subLine);
}
}
}
CommercialDocument sellingDocument = new CommercialDocument(documentType, amount,lineList,subLines,numDocument);
documentList.Add(sellingDocument);//adding all to the documentList
}
foreach (XElement closingSession in sessioneGiornaliera.Elements("ChiusuraSessione"))//list of closing sessions
{
int number = Convert.ToInt32(closingSession.Element("Numero")?.Value);
double equivalent = Convert.ToDouble(closingSession.Element("Corrispettivo")?.Value);
double totCancel = Convert.ToDouble(closingSession.Element("TotaleAnnullo")?.Value);
double totRefound = Convert.ToDouble(closingSession.Element("TotaleReso")?.Value);
string date = closingSession.Element("DataOra")?.Value;
string TX_dir = sessioneGiornaliera.Element("TrasmissioneCorrispettivi").Element("DatiCorrispettivi").Element("NomeFile")?.Value;
TX_dir = filename[0] + ":" + TX_dir; //gets the directory to wich the more specific XML files are stored
ClosingSession a = new ClosingSession(date, equivalent / 100, totCancel / 100, totRefound / 100, documentList, TX_dir, number);
closingSessionList.Add(a);
}
Itemcounter++;
}
}
else
MessageBox.Show("file type incompatible");
}catch // all the exeptions are already managed and showed in the Valida function
{
}
}```
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<x:MemoriaDettaglio xmlns:x="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/memoriadettaglio/export/v2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/memoriadettaglio/export/v2.0 Memoria_DettaglioV3.13.xsd" versione="3.0">
<Periodo integrale="false">
<Dal>2024-01-03T00:00:00</Dal>
<Al>2024-01-03T23:59:59</Al>
<MatricolaRT>STITE500777</MatricolaRT>
<LetturaDel>2024-01-03T14:59:05</LetturaDel>
<Parte>1</Parte>
<ChiaveConcatenazione>T/fk4maGA5vTmgFz31cGMFDwumG4OHF7ERS1cuUyqBg=</ChiaveConcatenazione>
<seTerminale>1</seTerminale>
</Periodo>
<RecordIdentificativoDGFE>
<DataOra>2024-01-01T16:45:12</DataOra>
<NumeroIdentificativo>1</NumeroIdentificativo>
<Misuratore>
<Matricola>STITE500777</Matricola>
</Misuratore>
</RecordIdentificativoDGFE>
<RecordCensimenti/>
<RecordAttivazioni/>
<RecordIntestazioni/>
<SessioniGiornaliere>
<SessioneGiornaliera>
<DataOra>2024-01-03T14:30:08</DataOra>
<PuntoVendita>
<PartitaIva>02498250345</PartitaIva>
</PuntoVendita>
<Modalita>RT</Modalita>
<DocumentiEmessi>
<DocumentoCommerciale>
<Vendita>
<DataOra>2024-01-03T14:30:08</DataOra>
<NumeroDocumento>0001</NumeroDocumento>
<NumeroAzzeramento>0008</NumeroAzzeramento>
<Dettaglio>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>6.00</Importo>
<Descrizione>REPARTO 01</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>6.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>5.00</Importo>
<Descrizione>REPARTO 02</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>5.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>10.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>1.00</Importo>
<Descrizione>REPARTO 01</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>1.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</Elemento>
<ModificatoreElemento>
<Importo>0.02</Importo>
<Segno>-</Segno>
<Descrizione>SCONTO</Descrizione>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</ModificatoreElemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<RigaSubtotale>
<SubTotale>11.98</SubTotale>
</RigaSubtotale>
</RigaGenerica>
</Dettaglio>
<ImportoTotale>11.98</ImportoTotale>
<Pagamenti>
<Pagamento>
<Importo>11.98</Importo>
<Tipo>PC</Tipo>
</Pagamento>
</Pagamenti>
</Vendita>
</DocumentoCommerciale>
</DocumentiEmessi>
<ChiusuraSessione>
<DataOra>2024-01-03T14:32:42</DataOra>
<Numero>8</Numero>
<Modalita>RT</Modalita>
<GranTotale>128.53</GranTotale>
<Corrispettivo>11.98</Corrispettivo>
<TotaleAnnullo>0.00</TotaleAnnullo>
<TotaleReso>0.00</TotaleReso>
<NumeroDocumentiCommerciali>1</NumeroDocumentiCommerciali>
</ChiusuraSessione>
<TrasmissioneCorrispettivi>
<DatiCorrispettivi>
<DataOra>2024-01-03T14:32:52</DataOra>
<NomeFile>\XML\SENT\CORR\OK\Z0001_Z0025\202401031432_Z0008.xml</NomeFile>
<RispostaNomeFile>\XML\SENT\CORR\OK\Z0001_Z0025\R_202401031432_Z0008.xml</RispostaNomeFile>
<Rif_Trasmissione_Telematica>155914705</Rif_Trasmissione_Telematica>
<StatoInvio>INVIATO</StatoInvio>
</DatiCorrispettivi>
</TrasmissioneCorrispettivi>
</SessioneGiornaliera>
<SessioneGiornaliera>
<DataOra>2024-01-03T14:52:20</DataOra>
<PuntoVendita>
<PartitaIva>02498250345</PartitaIva>
</PuntoVendita>
<Modalita>RT</Modalita>
<DocumentiEmessi>
<DocumentoCommerciale>
<Vendita>
<DataOra>2024-01-03T14:52:20</DataOra>
<NumeroDocumento>0001</NumeroDocumento>
<NumeroAzzeramento>0009</NumeroAzzeramento>
<Dettaglio>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>4.00</Importo>
<Descrizione>REPARTO 01</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>5.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>6.00</Importo>
<Descrizione>REPARTO 02</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>6.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>10.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>5.00</Importo>
<Descrizione>REPARTO 01</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>5.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>9.00</Importo>
<Descrizione>REPARTO 01</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>9.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>22.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>1.00</Importo>
<Descrizione>REPARTO 02</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>1.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>10.00</AliquotaIVA>
</IVA>
</Elemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>9.00</Importo>
<Descrizione>REPARTO 03</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>9.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>4.00</AliquotaIVA>
</IVA>
</Elemento>
<ModificatoreElemento>
<Importo>0.54</Importo>
<Segno>-</Segno>
<Descrizione>SCONTO</Descrizione>
<IVA>
<AliquotaIVA>4.00</AliquotaIVA>
</IVA>
</ModificatoreElemento>
</Riga>
</RigaGenerica>
<RigaGenerica>
<Riga>
<Elemento>
<Importo>2.00</Importo>
<Descrizione>REPARTO 03</Descrizione>
<Quantita>1</Quantita>
<PrezzoUnitario>2.00</PrezzoUnitario>
<IVA>
<AliquotaIVA>4.00</AliquotaIVA>
</IVA>
</Elemento>
<ModificatoreElemento>
<Importo>0.04</Importo>
<Segno>-</Segno>
<Descrizione>SCONTO</Descrizione>
<IVA>
<AliquotaIVA>4.00</AliquotaIVA>
</IVA>
</ModificatoreElemento>
</Riga>
</RigaGenerica>
</Dettaglio>
<ImportoTotale>36.42</ImportoTotale>
<Pagamenti>
<Pagamento>
<Importo>36.42</Importo>
<Tipo>PC</Tipo>
</Pagamento>
</Pagamenti>
</Vendita>
</DocumentoCommerciale>
</DocumentiEmessi>
<ChiusuraSessione>
<DataOra>2024-01-03T14:54:43</DataOra>
<Numero>9</Numero>
<Modalita>RT</Modalita>
<GranTotale>164.95</GranTotale>
<Corrispettivo>36.42</Corrispettivo>
<TotaleAnnullo>0.00</TotaleAnnullo>
<TotaleReso>0.00</TotaleReso>
<NumeroDocumentiCommerciali>1</NumeroDocumentiCommerciali>
</ChiusuraSessione>
<TrasmissioneCorrispettivi>
<DatiCorrispettivi>
<DataOra>2024-01-03T14:54:52</DataOra>
<NomeFile>\XML\SENT\CORR\OK\Z0001_Z0025\202401031454_Z0009.xml</NomeFile>
<RispostaNomeFile>\XML\SENT\CORR\OK\Z0001_Z0025\R_202401031454_Z0009.xml</RispostaNomeFile>
<Rif_Trasmissione_Telematica>155914737</Rif_Trasmissione_Telematica>
<StatoInvio>INVIATO</StatoInvio>
</DatiCorrispettivi>
</TrasmissioneCorrispettivi>
</SessioneGiornaliera>
</SessioniGiornaliere>
</x:MemoriaDettaglio>
Everything in "real"† programming is contextual.
If the shape of the data is fixed, and the data size is reasonable, then you would typically use a serialization library; in the case of C#
XmlSerializeris probably ideal, and there are tools to automatically generate starter code from either a schema file or an example xml file.If the shape of the data is dynamic, you'd have to use a DOM API (
XDocument/XmlDocument), and/or something like xslt, but this is a more niche scenario.If the data volume is huge (i.e. too large to reasonably load into memory at once as either a DOM or a deserialized object model), you'd have to use a streaming API, for example
XmlReader; this is very much "hard mode", and is rarely needed.The code in the question appears to be manually implementing deserialization based on a DOM; this is the worst of both worlds:
If you post an example of the XML, people here can probably show you how to get that working with
XmlSerializerin minimal code.† the quotes here are parody; I hate gatekeeping - we don't need to disambiguate "real" developers
Partial example based on the xml example in the comments below; there are a lot of configuration options for
XmlSerializer, usually involving attributes -[XmlArray],[XmlElement]and[XmlAttribute]being the most common (there are others):with
and using the xml in the question: