2009-10-14 4 views
13

Sto l'analisi di un gran numero di file di grandi dimensioni e dopo la profilatura il mio collo di bottiglia è:Come costruire XmlNodes da XmlReader

XmlDocument doc = new XmlDocument(); 
doc.Load(filename); 

Questo approccio è stato molto utile perché ho potuto estrarre i nodi in questo modo:

XmlNodeList nodeList = doc.SelectNodes("myXPath"); 

sto passaggio a XmlReader, ma quando trovo l'elemento che ho bisogno di estrarre mi sono bloccato per quanto riguarda il come costruire un XmlNode da esso come non troppo familiarità con XmlReader:

XmlReader xmlReader = XmlReader.Create(fileName); 

while (xmlReader.Read()) 
{ 
    //keep reading until we see my element 
    if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     // How do I get the Xml element from the reader here? 
    } 
} 

Mi piacerebbe essere in grado di costruire un oggetto List<XmlNode>. Sono su .NET 2.0.

Qualsiasi aiuto apprezzato!

risposta

6

Il tipo XmlNode non ha un costruttore pubblico, quindi non è possibile crearli da soli. Avrete bisogno di avere un XmlDocument che è possibile utilizzare per creare loro:

XmlDocument doc = new XmlDocument(); 
while (xmlReader.Read()) 
{ 
    //keep reading until we see my element 
    if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     // How do I get the Xml element from the reader here? 
     XmlNode myNode = doc.CreateNode(XmlNodeType.Element, xmlReader.Name, ""); 
     nodeList.Add(myNode); 
    }   
} 
+1

sembra che si stiano creando nodi vuoti? – JohnIdol

+0

Sì, a meno che non aggiungiate nulla agli elementi (assegnando qualcosa alla proprietà 'InnerText' per esempio) saranno vuoti. –

+0

oh sì - ora sembra ovvio dato che sto solo passando il nome dell'elemento, grazie – JohnIdol

5

XmlReader e XmlDocument hanno un modo molto distinto di elaborazione. XmlReader non conserva nulla in memoria e utilizza un approccio forward-only invece di creare un albero DOM completo in memoria per XmlDocument. È utile quando le prestazioni sono un problema, ma richiede anche che tu scriva la tua applicazione in modo diverso: invece di usare XmlNode, non tieni nulla e procedi solo "in movimento": cioè, quando un elemento passa da quello di cui hai bisogno , fai qualcosa. Questo è vicino all'approccio SAX, ma senza il modello di callback.

La risposta a "come ottenere XmlElement" è: dovrete crearli da zero in base alle informazioni del lettore. Questo, sfortunatamente, sfida il guadagno in termini di prestazioni. Spesso è meglio evitare di utilizzare completamente gli approcci DOM una volta che si passa a XmlReader, a meno che non si tratti di alcuni casi distinti.

Inoltre, il "molto pratico" modo di estrarre nodi usando XPath (SelectNodes è quello che viene mostrato sopra) non può essere utilizzato qui: XPath richiede un albero DOM. Considera questo approccio un approccio di filtraggio: puoi aggiungere filtri a XmlReader e dirgli di saltare determinati nodi o leggere fino a un determinato nodo. Questo è estremamente veloce, ma un modo diverso di pensare.

4

Utilizzare questo metodo per XmlDocument.ReadNode. Inserire XmlReader nell'utilizzo dell'istruzione e utilizzare XmlReader.LocalName anziché Nome per rimuovere il prefisso dello spazio dei nomi.

1

Ho usato la seguente soluzione, quando ho dovuto inserire i dati da un XmlReader in un XmlDocumenht:

XmlReader rdr = cmd.ExecuteXmlReader(); 

XmlDocument doc = new XmlDocument(); 

// create a container node for our resultset 
XmlElement root = doc.CreateElement("QueryRoot"); 
doc.AppendChild(root); 

StringBuilder xmlBody = new StringBuilder(); 

while(rdr.Read()) 
{ 
    xmlBody.Append(rdr.ReadOuterXml()); 
} 

root.InnerXml = xmlBody.ToString(); 
12

non Perché basta fare il seguente?

XmlDocument doc = new XmlDocument(); 
XmlNode node = doc.ReadNode(reader); 
+0

già risposto. Vedi http://stackoverflow.com/questions/1566192/how-to-build-xmlnodes-from-xmlreader/1566333#1566333. –

+0

Questa è la risposta corretta poiché l'altro lascia dei nodi vuoti! –

0

Ecco il mio approccio:

public static IEnumerable<XmlNode> StreamNodes(
    string path, 
    string[] tagNames) 
{    
    var doc = new XmlDocument();    
    using (XmlReader xr = XmlReader.Create(path)) 
    { 
     xr.MoveToContent(); 
     while (true) { 
      if (xr.NodeType == XmlNodeType.Element && 
       tagNames.Contains(xr.Name)) 
      { 
       var node = doc.ReadNode(xr); 
       yield return node; 
      } 
      else 
      { 
       if (!xr.Read()) 
       { 
        break; 
       } 
      } 
     } 
     xr.Close(); 
    }       
} 
// Used like this: 
foreach (var el in StreamNodes("orders.xml", new string[]{"order"})) 
{ 
    .... 
} 

I nodi possono poi essere importati in un altro documento per ulteriori elaborazioni.