XML: GetElementByTagName vs SelectSingleNode Vs Serialize

Andrea Zani

di Andrea Zani, in .NET, martedì 6 luglio 2004 ore 00.03

Archiviato in:

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

Per inserire un commento, devi avere un account.

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



Segnala su: Facebook MSDN Social Twitter Segnalo Wikio Diggita Technorati Stumbleupon Google Yahoo FriendFeed Delicious Furl

Nella stessa categoria
I più letti del mese
TagCloud
BLOG INFO
  • 295 post, 201 commenti, 36 trackback
  • Feed blog e contenuti tecnici: RSS
  • Feed blog: RSS Atom
IN EVIDENZA