2009-11-06 2 views

답변

1

이 답변에 의해 정의 된 질문자가 자신의 XML을 변경 고려 완전히 잘못로

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

남자 나는 c.Parent와 가까운 soo이었다. 그러나 단지 didnt는 속성을 본다. .. 고맙다! –

1

당신은 선조() 메서드 또는 부모 속성을 사용합니다. 이것을 삭제해야합니까?

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을 추가하는 것은 적절한 해결책을 통해 혼란이 있기 때문에 사용했습니다. 여기입니다, null 또는 선택 속성의 문제로

자른 :

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>"); 
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())); 

다음을 수행하여 별도의 foreach 루프 추한 캐스트를 제거 할 수 있습니다 null 속성을 처리하기위한 확장 메소드를 추가하는 방법에 대한 예를 들어, 확장 메소드의 두 번째 매개 변수 인 경우 null 속성을 사용할 기본 값을 전달할 수 있습니다.

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>"); 

대신의 모든 분야를 찾고 다음 각 부모를 확인하십시오

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을 만들기 위해 메시지 루트 요소와 닫는 태그를 추가 당신이 조사 할 분야가 적어 질 수 있도록 당신이 끼어 들었던 한 부모를 찾으십시오 :

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); 

편집 :
message 요소에 다른 종류의 요소가 포함되어있는 경우 자식 요소에 대해 "field"지정자가 추가되었습니다.

편집 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

이 잘못을 얻으려면 두 번째 사람. OQ는 말했다 : // 부모 노드 (메시지)가 (id = "P") 속성을 가지고 있는지 확인하는 방법 그의 Person은 Car를 가지고있다. 그 사람과 차가 아니라, 그 사람은 차를 가지고있다. – jfar

+0

@jfar : 너 무슨 소리 야? 왜 메시지 노드 안에 메시지 노드가 있다고 생각합니까? – Guffa

+0

맞습니다. 두 개의 개별 메시지가 아니라 메시지에 메시지가 있습니다. – jfar