2015-07-14 26 views
5

Ho un piccolo problema con la lettura di informazioni da un file xml ...Leggi xml dal file

Il file passato a me ha migliaia di righe. Sono interessato solo a 300 - 400 di quelle linee. Non è necessario scrivere alcun dato su xml quando l'utente ha terminato la sua operazione e i dati da leggere possono essere memorizzati in un List<string>.

Ho trovato soluzioni in rete utilizzando XmlTextReader per leggere i dati. Quindi non dovrei creare una classe e usare un serializzatore. Ma mi sembra im usando il XmlTextReader sbagliato. Forse mi può aiutare ...

Questo è come l'XML assomiglia:

<?xml version="1.0" encoding="utf-8"?> 
<ProjectConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <ProjectLists xmlns="..."> 
    <ProjectList> 
    ... // not interested in this data 
    </ProjectList> 
    <ProjectList> 
    <ListNode> 
    <Name>Test_Environment</Name> 
    <Children> 
     <ListNode> 
     <Name>yyy</Name> 
     <Children> 
      <ListNode> 
      <Name>205 (ST)</Name> 
      <Children> 
       <ListNode> 
       <Name>098-0031</Name> 
       <Children /> 
       </ListNode> 
       <ListNode> 
       <Name>098-0032</Name> 
       <Children /> 
       </ListNode> 
       //more ListNodes... 
      </Children> 
      </ListNode> 
      <ListNode> 
      <Name>old</Name> 
      <Children> 
       <ListNode> 
       <Name>W098-32</Name> 
       <Children /> 
       </ListNode> 
      </Children> 
      </ListNode> 
     </Children> 
     </ListNode> 
     <ListNode> 
     <Name>xxx</Name> 
     <Children /> 
     </ListNode> 
     <ListNode> 
     <Name>098-0001</Name> 
     <Children /> 
     </ListNode> 
     <ListNode> 
     <Name>098-0011</Name> 
     <Children /> 
     </ListNode> 
     // More List Nodes 
    </Children> 
    </ListNode> 
    <ListNode> 
    // more List Nodes 
    </ListNode> 
</ProjectList> 
<ProjectList> 
    //more uninteresting ProjectLists... 
</ProjectList> 

Mi interessa solo in Value degli Elementi nome più interne (le prime due sarebbe "098-0031" e "098-0032").

E questo è il mio codice:

while (reader.Read()) { 
      switch (reader.NodeType) { 
       case XmlNodeType.Element: 
        { 
         if (reader.Name == "Name") { 
          reader.Read(); 
          if (reader.Value == "Test_Environment") { 
           reader.ReadToDescendant("Children"); 
           if (reader.Name == "Children") { 
            reader.ReadToDescendant("Children"); 

           } 
          } 
         } 
        } 
        break; 
      } 
     } 

Ma la condizione reader.Name == "Children" è mai esaudito ... Qualcuno può spiegarmi perché. E magari mostrarmi un modo semplice per memorizzare quei valori in un List<string>? Grazie in anticipo!

MODIFICA: ho modificato il xml. Ci scusiamo per questo, ma la sua davvero difficile filtrare le parti confuse unnecassary dal mio xml ...

+0

È possibile utilizzare altri come 'Linq2XML'? –

+0

@SkyFang Assolutamente possibile – user3596113

risposta

2
static void GetMostInnerName() 
{ 
    string xml = @"<ProjectConfiguration xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xsi=""http://www.w3.org/2001/XMLSchema-instance""> 
<ProjectLists> 
<ProjectList> 
<ListNode> 
<Name>Test_Environment</Name> 
<Children> 
<ListNode> 
<Name>yyy</Name> 
<Children> 
<ListNode> 
<Name>205 (ST)</Name> 
<Children> 
<ListNode> 
<Name>098-0031</Name> 
<Children /> 
</ListNode> 
<ListNode> 
<Name>098-0032</Name> 
<Children /> 
</ListNode> 
</Children> 
</ListNode> 
<ListNode> 
<Name>old</Name> 
<Children> 
    <ListNode> 
    <Name>W098-32</Name> 
    <Children /> 
    </ListNode> 
</Children> 
</ListNode> 
</Children> 
</ListNode> 
<ListNode> 
<Name>xxx</Name> 
<Children> 
<ListNode> 
<Name>098-0001</Name> 
<Children /> 
</ListNode> 
<ListNode> 
<Name>098-0011</Name> 
<Children /> 
</ListNode> 
</Children> 
</ListNode> 
// more List Nodes 
</Children> 
</ListNode> 
</ProjectList></ProjectLists> 
</ProjectConfiguration>"; 
    XElement root = XElement.Parse(xml).Element("ProjectLists"); 
    //var xmlns = root.GetDefaultNamespace(); 
    //Console.WriteLine(xmlns); 
    var eles = root.Elements("ProjectList").SelectMany(x => x.Elements("ListNode")); 
    List<string> list = new List<string>(); 
    foreach (var ele in eles) 
    { 
     Loop(ele, list); 
    } 
    list.ForEach(x => 
    { 
     Console.WriteLine(x); 
    }); 
} 
static void Loop(XElement ele, List<string> list) 
{ 
    var child = ele.Element("Children"); 
    if (child != null && child.HasElements) 
    { 
     foreach (var e in child.Elements("ListNode")) 
     { 
      Loop(e, list); 
     } 
    } 
    else 
    { 
     list.Add(ele.Element("Name").Value); 
    } 
} 

Perché il vostro XML ha molti nodi come ProjectList, quindi ho usato SelectMany qui, e mi aggiungi root elemento di avere un test, l'ultima uscita è

098-0031 
098-0032 
W098-32 
098-0001 
098-0011 
+0

Grazie, ma 'eles' è vuoto per me – user3596113

+0

Sì, dovresti usare' root.Element (xxx) .Element (yyy).Elementi ("Elenco progetti") ', perché non conosco la struttura ad albero –

+0

OK Ho modificato il mio Xml. Scusa per questo ... – user3596113

0

Può questo aiuto? :)

   string path = @"path.xml"; 

        if(File.Exists(path)){ 
       XmlTextReader reader = new XmlTextReader(path); 

       Console.WriteLine(""); 
       while (reader.Read()) 
       { 
        switch (reader.NodeType) 
        { 

         case XmlNodeType.Element: 
          Console.Write("<" + reader.Name); 
          Console.WriteLine(">"); 
          break; 

         case XmlNodeType.Text: 
          Console.WriteLine(reader.Value); 
          break; 
         case XmlNodeType.EndElement: 
          Console.Write("</" + reader.Name); 
          Console.WriteLine(">"); 
          break; 
        } 
       } 
       Console.ReadLine(); 
        }else{ 
         Console.WriteLine("Error file not found"); 
        } 
0

che lingua è questo? Attraverserai l'XML in modo simile a JSON, utilizzando i tag.

0

Usa LinqToXml

var xDocument = XDocument.Parse("yourXmlString"); 
     XNamespace ns = xDocument.Root.GetDefaultNamespace(); 
     var result = (from e in xDocument 
          .Descendants(ns + "ListNode").Descendants(ns + "Children") 
          .Descendants(ns + "ListNode").Descendants(ns + "Children") 
          .Descendants(ns + "ListNode").Descendants(ns + "Children") 
          .Descendants(ns + "ListNode") 
          select e.Element(ns + "Name").Value).ToList(); 
+0

Grazie mille per il vostro aiuto. Perché la prima riga lancia un XmlException (Dati non validi nella riga 1 posizione 1) mentre questo non funziona: 'XmlTextReader reader = new XmlTextReader (" MyXmlString ");'? La mia prima riga appare così: '' – user3596113

+0

@ user3596113 Usa '\\' 'prima delle virgolette come' ' –

+0

Se vuoi per utilizzare una stringa XML codificata in modo rigido quindi utilizzare il back-slash prima delle doppie virgolette come '' altrimenti non è necessario se si ottiene dal server –

1
private static void FillNames(XElement container, List<string> result) 
{ 
    XElement[] listNodes = container.Elements("ListNode").ToArray(); 
    if (!listNodes.Any()) 
     return; 

    foreach (XElement listNode in listNodes) 
    { 
     XElement nameElement = listNode.Element("Name"); 
     if (nameElement == null) 
      continue; 

     XElement childrenElement = listNode.Element("Children"); 
     if (childrenElement == null) 
      continue; 

     if (!childrenElement.HasElements) 
      result.Add(nameElement.Value); 
     else 
      FillNames(childrenElement, result); 
    } 
} 

static void Main(string[] args) 
{ 
    var result = new List<string>(); 

    string xml = Resources.Xml; // TODO: put your xml here 

    XDocument doc = XDocument.Parse(xml); 
    if (doc.Root == null) 
     return; 

    XElement[] projects = doc.Root.Elements("ProjectList").ToArray(); 

    foreach (XElement project in projects) 
     FillNames(project, result); 
}