2012-11-30 7 views
5

Sto riscrivendo del codice che utilizza un XmlDocument per analizzare alcuni XML. Voglio utilizzare un XmlReader per vedere se riesco a ottenere alcuni miglioramenti delle prestazioni. La struttura del file XML è simile al seguente:Utilizzo della classe XmlReader per analizzare XML con elementi con lo stesso nome

<items> 
    <item id="1" desc="one"> 
     <itemBody date="2012-11-12" /> 
    </item> 
    <item id="2" desc="two"> 
     <itemBody date="2012-11-13" /> 
    </item> 
    <item id="3" desc="three"> 
     <itemBody date="2012-11-14" /> 
    </item> 
    <item id="4" desc="four"> 
     <itemBody date="2012-11-15" /> 
    </item> 
</items> 

Fondamentalmente, ho bisogno di scorrere tutti gli elementi <item>. Come ho detto, il vecchio codice funziona così:

XmlDocument document = new XmlDocument(); 

// load XML into XmlDocument 
document.LoadXml(xml); 

// use xpath to split into individual item 
string xPath = @"items/item"; 
XmlNodeList nodeList = document.SelectNodes(xPath); 

// loop through each item 
for (int nodeIndex = 0; nodeIndex < nodeList.Count; nodeIndex++) 
{ 
    // do something with the XmlNode 
    nodeList[nodeIndex]; 
} 

Questo funziona bene, ma credo che con un XmlReader sarebbe più veloce. Così ho scritto questo:

XmlReader xmlReader = XmlReader.Create(new StringReader(xml)); 

while (xmlReader.Read()) 
{      
    if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     string id = xmlReader.GetAttribute("id");     
     string desc = xmlReader.GetAttribute("desc"); 
     string elementXml = xmlReader.ReadOuterXml(); 
    } 
} 

Tuttavia, questo codice si legge solo il primo elemento <item>. ReadOuterXml() interrompe il ciclo. Qualcuno sa come aggirare questo? Oppure questo tipo di analisi non è possibile con un XmlReader? Ho dover fare questa versione di .NET utilizzando 2 :(quindi non posso usare LINQ

+1

Cosa succede dopo il primo elemento? Che debugging hai fatto? Il tuo codice originale * è effettivamente * troppo lento? (Non scrivere codice più difficile solo per * potenzialmente * rendere le cose più veloci se sono già abbastanza veloci ...) –

+0

questa non è una risposta, ma ... hai usato xsd2code? È molto utile analizzare il codice XML nelle classi –

+0

Qual è il valore restituito da questo? new StringReader (xml) .ReadToEnd() – laszlokiss88

risposta

1

Il seguente sembra funzionare: -.

 StringBuilder xml = new StringBuilder(); 

     xml.Append("<items>"); 
     xml.Append("<item id=\"1\" desc=\"one\">"); 
     xml.Append("<itembody id=\"10\"/>"); 
     xml.Append("</item>"); 
     xml.Append("<item id=\"2\" desc=\"two\">"); 
     xml.Append("<itembody id=\"20\"/>"); 
     xml.Append("</item>"); 
     xml.Append("<item id=\"3\" desc=\"three\">"); 
     xml.Append("<itembody id=\"30\"/>"); 
     xml.Append("</item>"); 
     xml.Append("</items>"); 

     using (XmlTextReader tr = new XmlTextReader(new StringReader(xml.ToString()))) 
     { 
      bool canRead = tr.Read(); 
      while (canRead) 
      { 
       if ((tr.Name == "item") && tr.IsStartElement()) 
       { 
        Console.WriteLine(tr.GetAttribute("id")); 
        Console.WriteLine(tr.GetAttribute("desc")); 
        string outerxml = tr.ReadOuterXml(); 
        Console.WriteLine(outerxml); 

        canRead = (outerxml != string.Empty); 
       } 
       else 
       { 
        canRead = tr.Read(); 
       } 
      } 
     } 
4

appena testato il codice in LINQPad funziona bene

var xml = @"<items> 
    <item id='1' desc='one' /> 
    <item id='2' desc='two' /> 
    <item id='3' desc='three' /> 
    <item id='4' desc='four' /> 
</items>"; 
XmlReader xmlReader = XmlReader.Create(new StringReader(xml)); 

while (xmlReader.Read()) 
{ 
    if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     string id = xmlReader.GetAttribute("id");    
     string desc = xmlReader.GetAttribute("desc"); 
     Console.WriteLine("{0} {1}", id, desc); 
    } 
} 

uscita:...

1 one 
2 two 
3 three 
4 four 

forse c'è qualcosa che non va con il tuo XML

+0

E sei sicuro che stai usando la libreria .NET 2.0? –

+0

Ciao Oleg, ho appena aggiornato la mia domanda. Ho dimenticato di dire che ho bisogno di estrarre l'elemento xml. –

0

Se è possibile utilizzare LINQ, ecco un modo alternativo:

class Program 
{ 
    static void Main(string[] args) 
    { 

     const string xml = @"<items> 
          <item id='1' desc='one'> 
          <itemBody date='2012-11-12' /> 
          </item> 
          <item id='2' desc='two'> 
          <itemBody date='2012-11-13' /> 
          </item> 
          <item id='3' desc='three'> 
          <itemBody date='2012-11-14' /> 
          </item> 
          <item id='4' desc='four'> 
          <itemBody date='2012-11-15' /> 
          </item> 
         </items>"; 

     var xmlReader = XmlReader.Create(new StringReader(xml)); 

     XElement element = XElement.Load(xmlReader, LoadOptions.SetBaseUri); 

     IEnumerable<XElement> items = element.DescendantsAndSelf("item"); 

     foreach (var xElement in items) 
     { 
      string id = GetAttributeValue("id", xElement); 
      string desc = GetAttributeValue("desc", xElement); 
      string itemBody = GetElementValue("itemBody", "date", xElement); 

      Console.WriteLine("id = {0}, desc = {1}, date = {2}", id, desc, itemBody); 
     } 

     Console.ReadLine(); 
    } 

    private static string GetElementValue(string elementName, string attributeName, XElement element) 
    { 
     XElement xElement = element.Element(elementName); 

     string value = string.Empty; 

     if (xElement != null) 
     { 
      XAttribute xAttribute = xElement.Attribute(attributeName); 

      if (xAttribute != null) 
      { 
       value = xAttribute.Value; 
      } 
     } 

     return value; 
    } 

    private static string GetAttributeValue(string attributeName, XElement element) 
    { 
     XAttribute xAttribute = element.Attribute(attributeName); 

     string value = string.Empty; 
     if (xAttribute != null) 
     { 
      value = xAttribute.Value; 
     } 

     return value; 
    } 
} 
+0

Ciao Justin, grazie per la risposta ma come ho detto nella mia domanda ho dovuto fare ciò usando .NET versione 2 :(Quindi non posso usare LINQ. –