2011-08-16 21 views
1

どうすればこのようなLinqクエリを行うことができますか?Linqの2つのコレクションで異なるサブ要素を見つける

私はdoc1.xmlとdoc2.xmlという2つのXML文書を持っています。どのようにしてdoc2の "file"要素が "path"属性と全く同じ "file"要素を持つが、doc1のこの "file"の "link"子要素は "absolutepath"属性を持つdoc1の各 "file" doc2の対応する "file"要素の1つ以上の "absolutepath"属性と同じではありませんか?

簡単な例:

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

EDIT:あなたが使用することができ、バックこれらのファイルのリンク要素を取得する:

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; 

それは再び文書を照会するために恥のビットだが、そこに我々行く...

(あなたは正確に正しいビットに得ることができるので、私はlink要素ではなく、ファイルの要素を選択している - 。あなたは、常にファイルを取得する親要素を選択することができます)

EDIT :

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

@アンダー:「例外」の仕組みのために、*やや微妙なことです。あなたは要素を投影に入れてもよいが、MoreLINQの 'ExceptBy'を使うことができます。 –

+0

Okですが、別のクエリを簡単に実行する方法はありますか?そのXElementsファイルをdoc1から取得します。あなたの質問の結果? – Anders

関連する問題