635 messaggi dal 11 febbraio 2013
Avendo un xml cosi strutturato
<?xml version="1.0" encoding="iso-8859-1"?>
<documento>
  <table name="Ordini">
    <riga>
      <field name="Anno">2018</field>
      <field name="Linea">001</field>
   ...
 </riga>
....


Debbo leggere l'xml e inserire i dati in un database
ho provato cosi (non ho mai usato Linq to xml)
 var ordini = from ord in doc.Descendants("table")
                         .Where(i => (string)i.Attribute("name") == "Ordini")
                         .Descendants("field")
                         select ord;

foreach(var item in ordini)
{ 
  Console.WriteLine(item.Attribute("name").Value + ": " + item.Value);
}



In questo modo leggo correttamente il nome dei field e il valore
ma come posso accedere a IEnumerable<XElement> e sapere il campo che debbo associare alla classe Ordini ?
non credo che si debba fare :
var anno = item.Attribute("name").Value == "Anno" ? item.Value : null;

il problema è che ottengo elementi nulli

se però filtro un campo ottengo il giusto numero di righe(riga)
from ord in doc.Descendants("table")
                         .Where(i => (string)i.Attribute("name") == "Ordini")
                         .Descendants("field")
                         .Where(e=>e.Attribute("name").Value=="Anno")
                         select ord;

ma come posso filtrare tutti i campi nel metodo di estenzione where ???
Modificato da jjchuck il 25 aprile 2018 18.48 -
635 messaggi dal 11 febbraio 2013
Sto provando con XmlReader
il problema è instanziare la mia classe per ogni elemento <row>

 List<SFA_ORDCLIENTE> listaOrdini = new List<SFA_ORDCLIENTE>();
            using (XmlReader reader = XmlReader.Create(new StreamReader(filename), settings))
            {
                while (reader.Read())
                {
                    if (reader.Name == "row")
                    {
                        SFA_ORDCLIENTE ordine = new SFA_ORDCLIENTE();
                        
                        foreach (var field in reader.Name=="field")
                        {
                          è qui che debbo crere un elemento ?
                        }
                        while (reader.NodeType == XmlNodeType.Element && reader.Name == "field")
                        {
                            XElement el = XNode.ReadFrom(reader) as XElement;
                            if (el != null)
                            {
                                var elName = el.Attribute("name").Value;

                                switch (elName)
                                {
                                    case "RolAnno":
                                        ordine.Anno = Convert.ToInt16(el.Value);
                                        break;
                                    case "RolCodatt":
                                        ordine.Codatt = el.Value;
                                        break;
                                    case "RolCodcen":
                                        ordine.Codcen = el.Value;
                                        break;

                                }
                                if (ordine != null) listaOrdini.Add(ordine);
                            }

                        }
                    }
                   

                }

Modificato da jjchuck il 26 aprile 2018 16.31 -
10.748 messaggi dal 09 febbraio 2002
Contributi
Dunque... se il file è gigante va bene usare XmlReader, che non ti costringe a pre-caricare il contenuto dell'intero file in memoria.


SFA_ORDCLIENTE ordine = new SFA_ORDCLIENTE();

Ok, questo va bene lì dove si trova.


foreach (var field in reader.Name=="field")
{
//è qui che debbo crere un elemento ?
}

Questo non l'ho capito. Fai un ciclo foreach su un bool? Credo che non serva, puoi eliminarlo.


if (ordine != null) listaOrdini.Add(ordine);

Questo prova a spostarlo subito sotto, fuori dal ciclo while.

In alternativa all'XmlReader, ma solo se il file è di dimensioni contenute, puoi deserializzarlo in una tua classe. Fai così: copia l'xml e da Visual Studio crea un nuovo file di codice, poi clicca il menu Modifica -> Incolla speciale -> Incolla XML come classi. Visual Studio ti creerà tutto l'albero di classi appropriato a deserializzare l'xml. Se le classi che vengono create non ti soddisfano, puoi modificarle a piacimento, purché usi in maniera accorta gli attributi di mapping XML.
https://docs.microsoft.com/en-US/dotnet/standard/serialization/controlling-xml-serialization-using-attributes

Segui questo esempio per fare la deserializzazione.
https://msdn.microsoft.com/it-it/library/tz8csy73(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

ciao,
Moreno
Modificato da BrightSoul il 26 aprile 2018 21.14 -

Enjoy learning and just keep making
635 messaggi dal 11 febbraio 2013
E da ieri che provo...sto impazzendo

Ho provato a spostare il codice ma la lista rimane vuota: quando trova row il reader non entra nel secondo while

Cmq il link per deserializzare non trova la pagina

Grazie per l'aiuto
10.748 messaggi dal 09 febbraio 2002
Contributi
Sistemato il link, vai ora

Enjoy learning and just keep making
635 messaggi dal 11 febbraio 2013
Ho RIprovato questo con LINQ e sembra funzionare
debbo solo fare due query perchè due sono le tabelle

Che ne pensi?
Si può ottimizzare questo codice ?



 var doc = XDocument.Load(filename);
            var ordcli = doc.Descendants("table")
                         .Where(i => (string)i.Attribute("name") == "ordcli")
                         .Descendants("row")
                         .Select(e => e.Elements());

            
            List<SFA_ORDCLI> sfaOrdcliList = new List<SFA_ORDCLI>();
            foreach (var row in ordcli)
            {              
                SFA_ORDCLI sfaOrdcli = new SFA_ORDCLI();
             
                foreach (var field in row)
                {
                    var name = (string)field.Attribute("name");
                    
                    switch (name)
                    {
                        case "RolAnno":
                            sfaOrdcli.RolAnno = Convert.ToInt16((string)field);
                            break;
                       
                        case "RolCodcen":
                            sfaOrdcli.RolCodcen = (string)field;
                            break;
                       
                        case "RolTotord":
                            sfaOrdcli.RolTotord = Convert.ToDouble((string)field);
                            break;
                        ....
                    }              
                }
                if (sfaOrdcli != null) sfaOrdcliList.Add(sfaOrdcli);
            }


            foreach (var item in sfaOrdcliList)
            {
                Console.WriteLine(item.ToString()); //override tostring
            }
635 messaggi dal 11 febbraio 2013
Anche cosi funziona
se mai dovesse servire a qualcuno

Ora debbo capire dove fare il check per le tabelle visto che sono 2 nell'xml

 List<SFA_ORDCLI> listaOrdini = new List<SFA_ORDCLI>();
            using (XmlReader reader = XmlReader.Create(new StreamReader(filename)))
            {
                SFA_ORDCLI ordine = new SFA_ORDCLI();
                reader.MoveToContent();
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name == "row")
                        {
                            XElement el =XNode.ReadFrom(reader) as XElement;
                            if (el != null)
                            {
                                IEnumerable<XElement> elements = el.Elements("field");
                                foreach (XElement element in elements)
                                {
                                    var elName = element.FirstAttribute.Value;
                                    switch (elName)
                                    {
                                        case "RolAnno":
                                            ordine.RolAnno = Convert.ToInt16(element.Value);
                                            break;
                                        case "RolCodatt":
                                            ordine.RolCodatt = element.Value;
                                            break;
                                        case "RolCodcen":
                                            ordine.RolCodcen = element.Value;
                                            break;
                                    }
                                }
                                if (ordine != null) {listaOrdini.Add(ordine); }
                            }
                        }
                    }
                }
            }

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.