2011-08-16 5 views
1

어떻게 Linq 쿼리를 수행 할 수 있습니까?Linq의 두 컬렉션에서 다른 하위 요소 찾기

두 개의 xml 문서 doc1.xml 및 doc2.xml이 있습니다. doc2의 "file"요소가 "path"속성과 완전히 동일한 "file"요소를 갖고 있지만 doc1에있는이 "file"의 "link"자식 요소는 "absolutepath"속성을 가진 doc1의 각 "file"요소를 어떻게 찾을 수 있습니까? doc2의 해당 "파일"요소에있는 하나 이상의 "절대 경로"속성과 동일하지 않습니까?

간단한 예 :

DOC1 :

<doc> 
    <file path="c:\temp\A.xml"> 
    <link absolutepath="c:\temp\B.xml"/> 
    <link absolutepath="c:\temp\C.xml"/> 
    </file> 
    <file path="c:\temp\C.xml"> <!--This should match, because it's child link absolutepath is not the same as child link absolutepath of the corresponding file with the same path in doc2--> 
    <link absolutepath="c:\temp\D.xml"/> 
    <link absolutepath="c:\temp\F.xml"/> 
    </file> 
</doc> 

doc2 :

<doc> 
    <file path="c:\temp\A.xml"> 
    <link absolutepath="c:\temp\B.xml"/> 
    <link absolutepath="c:\temp\C.xml"/> 
    </file> 
    <file path="c:\temp\C.xml"> 
    <link absolutepath="c:\temp\D.xml"/> 
    <link absolutepath="c:\temp\E.xml"/> 
    </file> 
</doc> 

어떤 아이디어가?

EDIT : 각 파일 요소에 대해 여러 링크로 무엇을 의미하는지 보여주는 xml 예제를 편집했습니다. 그래서 내가 원하는 것은 doc2의 링크 요소에서 찾을 수없는 절대 경로를 가진 링크 요소를 가진 doc1의 각 파일입니다. 그래서 실제로 같은 수의 링크가 있지만 절대 경로가 때때로 다를 수 있습니다. 링크 요소에 이러한 차이가있는 파일을 찾아서 추출하려고합니다. 내가 나중에 쿼리를 제외하고에서 올바른 결과를 얻을 수 없기 때문에,

여기에 여러 링크를 추출, 존에 의해 제안 쿼리를 수정 내 시도하지만 내가 잘못하고 있다고 생각 :

var files = from file in doc1.Descendants("file") 

       select new 
       { 
        file = file.Attribute("path").Value, 
        link = file.Elements("link").Attributes("absolutepath") 
       }; 
    var oldfiles = from file in doc2.Descendants("file") 
       from link in file.Elements("link") 
       select new 
       { 
        file = file.Attribute("path").Value, 
        link = file.Elements("link").Attributes("absolutepath") 
       }; 
    //Get the ones that are different between them 
    var missing = files.Except(oldfiles); 

답변

2

글쎄, XML 부분부터 시작하겠다. 당신이 단지 수 그럼 당신은 files1files2 (각 문서에 적용되는 위의 쿼리)가있는 경우

var files = from file in document.Descendants("file") 
      from link in file.Elements("link") 
      select new { file = file.Attribute("path").Value, 
         link = link.Attribute("absolutepath").Value }; 

:

나는 원래가 필요 이상이 더 복잡하게,하지만 난 당신이 바로 사용할 수있을 것 같아요
var extraFiles = files1.Except(files2); 

편집 :

var linkElements = from link in file.Descendants("link") 
        join extra in extraFiles on 
         new { file = link.Parent.Attribute("path").Value, 
           link = link.Attribute("absolutepath").Value } 
         equals extra 
        select link; 

그것은 다시 문서를 조회 할 수치의 비트,하지만 우리가 : 다시 해당 파일에 대한 링크 요소를 얻으려면, 당신은 사용할 수 있습니다

은 (당신이 딱 맞는 비트를 얻을 수 있도록 내가 링크 요소가 아닌 파일 요소를 선택한 - 당신은 항상 파일을 얻을 수있는 부모 요소를 선택할 수 있습니다.) ... 이동

편집 : 여러 개의 링크 요소가 있고 누락 된 요소가있는 파일을 찾으려면 실제로는 우리가 가지고있는 것부터 꽤 쉽습니다.

var justFiles = new HashSet<string>(extraFiles.Select(x => x.file).Distinct()); 
var fileElements = from element in file.Descendants("file") 
        where justFiles.Contains((string) element.Attribute("path") 
        select element; 
+0

고맙습니다. 하지만 실제로 XElement로 파일 요소를 쿼리에서 가져올 수있는 방법이 있습니까? 그게 내가 각 XElement에 물건을하기 위해 코드에서 다음에 사용하는 것입니다 ... – Anders

+0

@Anders : Except가 작동하는 방식 때문에 * 약간 * 까다 롭습니다. 요소를 프로젝션에 넣을 수 있지만 MoreLINQ의 ExceptBy를 사용하면 ... –

+0

그래도 다른 쿼리를 수행하는 쉬운 방법이 있습니다. doc1에서 XElements 파일의 경로 속성 값이 문자열 파일과 일치하는 파일을 가져 오는 것입니다. 당신 조회의 결과? – Anders