XML: GetElementByTagName vs SelectSingleNode Vs Serialize

di Andrea Zani, in .NET,

Premessa: in questi giorni sto giocando con delle piccole Forms Application in .Net, e per le varie configurazioni e dati utilizzo XML (interessa a qualcuno?).

Ieri, mentre scendevo in bici da un paesino alpino a 68 Km/h, mi è nato un dubbio. Per l'accesso a dati XML, per prestazioni, è meglio utilizzare l'ormai storico GetElementByTagName, il quasi nuovo SelectSingleNode con l'XPath, oppure la serializzazione del documento XML in una classe? (Alla faccia della concentrazione ciclistica! Anche questo interessa a qualcuno? Meno di niente, lo so!)

Non mi piace rimanere con i dubbi e ho fatto delle prove in merito. Essendo prove effettuate da me possono non essere del tutto veritiere o esatte, ma accetto qualsiasi smentita a riguardo.

Ma vediamo all'esempio realizzato. Innanzitutto ho scritto questo banale documento XML:

<?xml version="1.0"?>
<xml2>
  <nome1>0</nome1>
  <nome2>0</nome2>
  <nome3>0</nome3>
  <nome4>0</nome4>
  <nome5>0</nome5>
</xml2>

Quindi ho scritto 3 funzioni che eseguono le medesime operazione: prendono il valore numerico di ogni singolo nodo e aumentano tale numero di un'unità. Ecco la prima funzione:

void Funzione1()
{
   XmlDataDocument x=new XmlDataDocument();
   x.Load(Request.MapPath("XMLFile1.xml" ));
   XmlElement root=x.DocumentElement;
   XmlNodeList xx;
   xx=root.GetElementsByTagName("nome1");
   xx[0].InnerText=(Int32.Parse(xx[0].InnerText)+1).ToString();
   xx=root.GetElementsByTagName("nome2");
   xx[0].InnerText=(Int32.Parse(xx[0].InnerText)+1).ToString();
   xx=root.GetElementsByTagName("nome3");
   xx[0].InnerText=(Int32.Parse(xx[0].InnerText)+1).ToString();
   xx=root.GetElementsByTagName("nome4");
   xx[0].InnerText=(Int32.Parse(xx[0].InnerText)+1).ToString();
   xx=root.GetElementsByTagName("nome5");
   xx[0].InnerText=(Int32.Parse(xx[0].InnerText)+1).ToString();
   x.Save(Request.MapPath("XMLFile1.xml" ));
}

Molto semplice: letto il documento XML con la funzione GetElementByTagName viene preso il valore interessato e modificato. La seconda funzione utilizza il citato SelectSingleNode:

void Funzione2()
{
   XmlDataDocument x=new XmlDataDocument();
   x.Load(Request.MapPath("XMLFile1.xml" ));
   XmlElement root=x.DocumentElement;
   XmlNode xx;
   xx=root.SelectSingleNode(@"//nome1");
   xx.InnerText=(Int32.Parse(xx.InnerText)+1).ToString();
   xx=root.SelectSingleNode(@"//nome2");
   xx.InnerText=(Int32.Parse(xx.InnerText)+1).ToString();
   xx=root.SelectSingleNode(@"//nome3");
   xx.InnerText=(Int32.Parse(xx.InnerText)+1).ToString();
   xx=root.SelectSingleNode(@"//nome4");
   xx.InnerText=(Int32.Parse(xx.InnerText)+1).ToString();
   xx=root.SelectSingleNode(@"//nome5");
   xx.InnerText=(Int32.Parse(xx.InnerText)+1).ToString();
   x.Save(Request.MapPath("XMLFile1.xml" ));
}

L'ultima tecnica, la serializzazione del contenuto del file XML in una classe si basa su questo codice:

void Funzione3()
{
   xml2 x=null;
   using( FileStream stream = File.OpenRead( Request.MapPath("XMLFile1.xml" ) ))
   {
    XmlSerializer serializer = new XmlSerializer( typeof( xml2 ) );
    x=(xml2)serializer.Deserialize(stream);
   }
  x.nome1+=1; x.nome2+=1; x.nome3+=1; x.nome4+=1; x.nome5+=1;
   using( FileStream stream = File.OpenWrite( Request.MapPath("XMLFile1.xml" ) ))
   {
    XmlSerializer serializer = new XmlSerializer( typeof( xml2 ) );
    serializer.Serialize( stream, x );
   }
}

Questa tecnica è anche la più comoda visto che permette l'accesso ai singoli nodi come se fossero propietà di una classe. Confesso che tra le tre tecniche la mia preferita è la seconda: l'accesso ai singoli nodi con il SelectSingleNode o SelectNodes. L'ultima tecnica non l'avevo presa molto in considerazione per una mia ubbia personale: ero sicuro che tra le tre fosse quella con prestazioni peggiori per via della serializzazione e deserializzazione del documento XML in classe.

Mi sbagliavo.

Messe a confronto - nel mio test facevo eseguire questo codice centinaia di volte - per le stesse operazioni ecco i tempi:

  • Funzione1: 0,1638 s
  • Funzione2: 0,1872 s
  • Funzione3: 0,0945 s

??? La tecnica da me utilizza è la più lenta in assoluta e quella che io pensavo fosse la meno prestazionale che è più veloce del quasi 100%. Probabilmente questo è dovuto da una certa lentezza dovuta all'interpretazione della query XPath, ma che la serializzazione permettesse un aumento del genere non me l'aspettavo.

Vado a nascondermi...

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese