2009-11-06 2 views
2

Допустим, у вас есть XML вроде как это:Базовый синтаксис LINQ

<data> 
    <messages> 
    <message name="Person" id="P"> 
    <field name="FirstName" required="Y" /> 
    <field name="LastName" required="Y" /> 
    <field name="Sex" required="N" /> 
    </message> 
    <message name="Car" id="C"> 
    <field name="Make" required="Y" /> 
    <field name="Model" required="Y" /> 
    <field name="Year" required="N" /> 
    </message> 
    </messages> 
</data> 

Использование Linq, как бы вы получите список всех необходимых имен полей для лица?

Я только начал играть с LINQ/XML сегодня, это примерно так, как Ive получил.

var q = from c in loaded.Descendants("field") 
      where (string)c.Attribute("required") == "Y" && 
      // how to check the parent node (message) has an attribute (id="P")   
      select (string)c.Attribute("name"); 

    foreach (string name in q) 
     Console.WriteLine(name); 
+0

Вы не имеете XML, как это, это не действительный документ XML. Можете ли вы разместить фактический XML, который у вас есть, или, по крайней мере, рабочий пример? – Guffa

ответ

1

Этот ответ совершенно неправильно, учитывая спрашивающий изменил свое XML. Должен ли я удалить это.

var q = from c in loaded.Descendants("field") 
      where (string)c.Attribute("required") == "Y" && 
        c.Parent.Attribute("id").Value == "P" 
      select (string)c.Attribute("name"); 

Добавление Xml Я использовал, потому что есть некоторая путаница в правильном решении.

XDocument loaded = XDocument.Parse(@" 
<message name=""Person"" id=""P""> 
    <field name=""FirstName"" required=""Y"" /> 
    <field name=""LastName"" required=""Y"" /> 
    <field name=""Sex"" required=""N"" /> 
    <message name=""Car"" id=""C""> 
     <field name=""Make"" required=""Y"" /> 
     <field name=""Model"" required=""Y"" /> 
     <field name=""Year"" required=""N"" /> 
    </message> 
</message>"); 
+0

Человек, я был су ближе к c.Parent, но просто не видел атрибута ... Спасибо! –

2

вы можете удалить отдельный цикл Еогеасп и некрасивый оттенок, выполнив следующие действия, а также

(from c in myXML.Descendants("field") 
     where c.Attribute("required").Value == "Y" && 
     c.Parent.Attribute("id").Value == "P" 
     select c.Attribute("name").Value).ToList().ForEach(s => Console.WriteLine(s.ToString())); 

Edit:

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

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

namespace MyTestApp 
{ 

class Program 
{ 
    static void Main(string[] args) 
    { 
     XDocument myXML = XDocument.Load(@"C:\file.xml"); 

     (from c in myXML.Descendants("field") 
     where c.Attribute("required") 
       .GetAttributeValueOrDefault("N") == "Y" && 
       c.Parent.Attribute("id").Value == "P"  
     select 
     c.Attribute("name").Value).ToList().ForEach(s => Console.WriteLine(s.ToString())); 

     Console.ReadLine(); 
    } 
} 

public static class XLinqHelper 
{ 
    // extension method that handles an xattribute and returns the provided default if the Xattrib is null 
    public static string GetAttributeValueOrDefault(this XAttribute s, string defaultValue) 
    { 
     string retVal; 
     if (s == null) 
      retVal = defaultValue; 
     else 
      retVal = s.Value; 
     return retVal; 


    } 
} 

}

+0

странно, я получаю исключение NullReferenceException при использовании. Значение это для ваших и примеров Guffas. –

+0

Как вы загружаете XML – Matt

+0

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

2

Я добавил корневой элемент и закрывающий тег для сообщений, чтобы сделать XML действительный:

XDocument loaded = XDocument.Parse(@" 
    <messages> 
    <message name=""Person"" id=""P""> 
     <field name=""FirstName"" required=""Y"" /> 
     <field name=""LastName"" required=""Y"" /> 
     <field name=""Sex"" required=""N"" /> 
    </message> 
    <message name=""Car"" id=""C""> 
     <field name=""Make"" required=""Y"" /> 
     <field name=""Model"" required=""Y"" /> 
     <field name=""Year"" required=""N"" /> 
    </message> 
    </messages>"); 

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

IEnumerable<string> fields = 
    loaded.Root.Elements() 
    .Where(m => m.Attribute("id").Value == "P") 
    .Single() 
    .Elements("field") 
    .Where(f => f.Attribute("required").Value == "Y") 
    .Select(f => f.Attribute("name").Value); 

Редактировать:
Добавлен спецификатор «field» для дочерних элементов, если элемент сообщения содержит любые другие элементы.

Edit 2:
я соединял рабочий пример с подмножеством фактических данных:

XDocument loaded = XDocument.Parse(@" 
    <fix major=""4"" minor=""4""> 
    <header> 
    </header> 
    <trailer> 
    </trailer> 
    <messages> 
     <message name=""ResendRequest"" msgtype=""2"" msgcat=""admin""> 
     <field name=""BeginSeqNo"" required=""Y"" /> 
     <field name=""EndSeqNo"" required=""Y"" /> 
     </message> 
     <message name=""Reject"" msgtype=""3"" msgcat=""admin""> 
     <field name=""RefSeqNum"" required=""Y"" /> 
     <field name=""RefTagID"" required=""N"" /> 
     <field name=""RefMsgType"" required=""N"" /> 
     <field name=""SessionRejectReason"" required=""N"" /> 
     <field name=""Text"" required=""N"" /> 
     <field name=""EncodedTextLen"" required=""N"" /> 
     <field name=""EncodedText"" required=""N"" /> 
     </message> 
    </messages> 
    </fix>"); 

IEnumerable<string> fields = 
    loaded.Root.Element("messages").Elements("message") 
    .Where(m => m.Attribute("name").Value == "Reject") 
    .Single() 
    .Elements("field") 
    .Where(f => f.Attribute("required").Value == "Y") 
    .Select(f=>f.Attribute("name").Value); 
+0

2-й парень, чтобы получить это неправильно. OQ сказал: // как проверить родительский узел (сообщение) имеет атрибут (id = «P»). У Его Человека есть Автомобиль. Это не человек и автомобиль, у его лица есть автомобиль. – jfar

+0

@jfar: О чем вы говорите? Почему, по вашему мнению, есть узел сообщений внутри узла сообщения? – Guffa

+0

Правильно, есть сообщение в сообщении, а не два отдельных сообщения. – jfar