2015-10-23 10 views
1

Я довольно новичок в C#, и я действительно борюсь с этой проблемой.Разбор XML-поддеревьев

Так в основном у меня есть XML-файл, который выглядит так:

<groups> 
<group id="1" name="group1" location="null"> 
    <member id="1" name="Jack" age="32"/> 
    <member id="2" name="Tom" age="25"/> 
    <member id="3" name="John" age="32"/> 
</group> 
<group id="2" name="group2" location="null"> 
     <member id="1" name="Bob" age="31"/> 
     <member id="2" name="Michael" age="34"/> 
     <member id="3" name="Mike" age="44"/> 
</group> 

Это не совсем, но это следует точно такой же формат. Итак, что я хочу сделать, положить всех членов группы в свой собственный список. Таким образом, у каждой группы будет свой собственный список. Итак, Джек, Том, Джон (члены группы id 1) будут в списке1, а Боб, Майкл и Майк (члены группы id 2) будут в списке2. В настоящее время у меня это есть, это в основном ставит всех членов, независимо от их группы, в тот же список, чего я не хочу. Решение, вероятно, очень просто, у меня просто нет опыта работы с файлами XML, поэтому не знаю, как продвигаться с этим.

String XMLURL = "link_to_xml"; 

using (XmlTextReader reader = new XmlTextReader(XMLURL)) 
{ 
    while (reader.Read()) 
    { 
     switch (reader.NodeType) 
     { 
      case XmlNodeType.Element: 
       switch (reader.Name) 
       { 
        case "member": 
         if (reader.HasAttributes) 
         { 
          reader.MoveToAttribute(1); 
          players.Add(reader.Value.ToUpper()); 
         } 
         break; 
       } 
       break; 
      } 
     } 
    } 
} 
+0

Является ли XML-файл настолько огромным, что его нельзя загрузить в память? Если это так, необходим алгоритм потоковой передачи, такой как тот, который у вас есть. В противном случае Linq to XML обеспечивает гораздо более легкое решение. – dbc

+0

Зависит от того, что считается «огромным», он содержит от 50 до 400 записей и обновлений (новые записи добавляются и старые удаляются) каждые 20 секунд или около того. Я думаю, что это довольно большой? Итак, решение Linq работает только для «статических» XML-файлов? – ekl

+0

Нет, это не огромно, на самом деле это довольно мало. Огромное значение составляет 10 мегабайт или более, например. [Каков наилучший способ анализа (большого) XML в коде C#?] (Http://stackoverflow.com/questions/676274/what-is-the-best-way-to-parse-big-xml-in- с-острым-код). Linq to XML должно быть прекрасным. Но независимо от того, что вы используете, вам необходимо перезагрузить файл после изменения файла. – dbc

ответ

0

Вы можете легко это сделать с помощью XML Linq.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 
using System.Globalization; 


namespace ConsoleApplication53 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string xml = 
      "<groups>" + 
       "<group id=\"1\" name=\"group1\" location=\"null\">" + 
        "<member id=\"1\" name=\"Jack\" age=\"32\"/>" + 
        "<member id=\"2\" name=\"Tom\" age=\"25\"/>" + 
        "<member id=\"3\" name=\"John\" age=\"32\"/>" + 
       "</group>" + 
       "<group id=\"2\" name=\"group2\" location=\"null\">" + 
         "<member id=\"1\" name=\"Bob\" age=\"31\"/>" + 
         "<member id=\"2\" name=\"Michael\" age=\"34\"/>" + 
         "<member id=\"3\" name=\"Mike\" age=\"44\"/>" + 
       "</group>" + 
      "</groups>"; 

      XDocument doc = XDocument.Parse(xml); 
      var results = doc.Descendants("group").Select(x => new { 
       id = (int)x.Attribute("id"), 
       name = x.Attribute("name").Value, 
       location = x.Attribute("location").Value, 
       memebers = x.Elements("member").Select(y => new { 
        id = (int)y.Attribute("id"), 
        name = y.Attribute("name").Value, 
        age = (int)y.Attribute("age") 
       }).ToList() 
      }).ToList(); 
     } 

    } 
} 
+0

Получил это, работая с немного возиться, спасибо! – ekl

0

Вы можете использовать System.Xml.Linq как это:

private List<string[]> GetGroups(string xml) 
    { 
     List<string[]> result = new List<string[]>(); 
     XDocument document = XDocument.Parse(xml); 
     XElement groups = document.Root; 
     foreach (XElement group in groups.Elements("group")) 
     { 
      result.Add(group.Elements("member").Select(item => item.Attribute("name").ToString()).ToArray()); 
     } 
     return result; 
    } 

Я не запускать это с тестовым файлом. Я просто хотел дать вам представление о том, как использовать классы пространства имен System.Xml.Linq.

+0

Я получаю «Данные на корневом уровне недействительны. Строка 1, позиция 1.' с помощью XDocument.Parse. Файл XML, который я использую, имеет расширение .php (оно называется «xml.php», но это просто чистый XML), может ли это вызвать ошибку? XmlTextReader не имеет никаких проблем с его чтением. XML-файл не управляется мной, поэтому я не могу его изменить, если это вызывает проблему, и это динамично, поэтому я не могу вручную их исправить. – ekl

+0

У вас может быть какой-то странный символ в начале файла. Что такое первый персонаж? – Lorek

+0

@bulf - Вероятно, в начале строки есть [символ байтового порядка] (https://en.wikipedia.org/wiki/Byte_order_mark). Как вы загрузили файл в память? Было бы лучше использовать ['XDocument.Load (string filename)'] (https://msdn.microsoft.com/en-us/library/bb343181.aspx), так как считыватель внутреннего потока должен удалять спецификацию. – dbc