C # Чтение нескольких элементов с одинаковым именем с использованием LINQ to XML - PullRequest
0 голосов
/ 27 июня 2011

Есть ли лучший способ сделать это? Я должен получить оба значения свойств. XML всегда имеет только эти 2 свойства.

Мой xml:

<Template name="filename.txt">
  <Property name="recordSeparator">\r\n</Property>
  <Property name="fieldCount">16</Property>
</Template>

Linq:

            var property = from template in xml.Descendants("Template")
                       select new
                                  {
                                      recordDelim = template.Elements("Property").Where(prop => prop.Attribute("name").Value == "recordSeparator")
                                                    .Select(f => new { f.Value }),
                                      fieldCount = template.Elements("Property").Where(prop => prop.Attribute("name").Value == "fieldCount")
                                                    .Select(f => new { f.Value })
                                  };

Ответы [ 2 ]

3 голосов
/ 27 июня 2011

«Лучший путь» зависит от того, чего именно вы пытаетесь достичь - производительности, простоты и т. Д .?

Полагаю, я бы создал класс, содержащий то, что вы пытаетесь получить с помощью анонимных классов.

public class Item {
    public String Separator { get; set; }
    public int FieldCount { get; set; }
}

и затем я бы изменил LINQ на:

var templates = from template in xml.Descendants("Template")
                let children = template.Elements("Property")
                select new Item() {
                    Separator = children.First(tag=>tag.Attribute("name").Value == "recordSeparator").Value,
                    FieldCount = Int32.Parse(children.First(tag=>tag.Attribute("name").Value == "fieldCount").Value)
                };

List<Item> items = templates.ToList();

Обратите внимание, что это вызовет исключение NullReference в случае, если ваш тег Template не содержит два тега Property, каждый с указаннымАтрибуты.

Также он выдаст исключение при разборе целого числа из FieldCount, если это не число.

Идея:

Если xmlгенерируется самостоятельно, и вы можете изменить его формат, почему бы не сделать что-то вроде:

<Template>
  <Name>filename.txt</Name>
  <RecordSeparator>\r\n</RecordSeparator>
  <FieldCount>16</FieldCount>
</Template>

Его легче читать и анализировать, и он немного короче.

ВВ конце концов, я думаю, вот как я бы это сделал:

Имея этот класс:

public class Item 
{
   public String FileName { get; set; }
   public String Separator { get; set; }
   public int FieldCount { get; set; }
}

и этот закрытый метод:

private Item GetItemFromTemplate(XElement node) 
{
    return new Item() {
        FileName = node.Element("Name").Value,
        Separator = node.Element("RecordSeparator").Value,
        FieldCount = Int32.Parse(node.Element("FieldCount").Value)
    }; 
}    

Я мог бы сделать в коде:

XDocument doc = XDocument.Load("myfile.txt");

List<Item> items = (from template in doc.Elements("Template")
                   select GetItemFromTemplate(template)).ToList();
1 голос
/ 27 июня 2011

Это немного более эффективно:

var properties =
    from template in xml.Descendants("Template")
    let propertyNodes = template.Elements("Property")
        .Select(arg => new { Name = arg.Attribute("name").Value, Value = arg.Value })
    select
        new
        {
            recordDelim = propertyNodes.Single(arg => arg.Name == "recordSeparator").Value,
            fieldCount = propertyNodes.Single(arg => arg.Name == "fieldCount").Value
        };

Если у вас всегда один Template узел:

var propertyNodes = xml.XPathSelectElements("/Template/Property")
    .Select(arg => new { Name = arg.Attribute("name").Value, arg.Value })
    .ToList();

var properties =
    new
    {
        recordDelim = propertyNodes.Single(arg => arg.Name == "recordSeparator").Value,
        fieldCount = propertyNodes.Single(arg => arg.Name == "fieldCount").Value
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...