1

現在のバージョン (B) と以前のバージョン (A) の 2 つの xml ファイルがあります。

Id 属性に基づいて変更された属性があるかどうかを確認したい場合、その要素と、現在のファイルに追加された新しい要素を取得したい (B)

したがって、変更と新しい要素を含む要素の結果のxmlファイルが得られます

---- Version A
<Books>
    <book id='1' image='C01' name='C# in Depth'/>
    <book id='2' image='C02' name='ASP.NET'/>
    <book id='3' image='C03' name='LINQ in Action '/>
    <book id='4' image='C04' name='Architecting Applications'/>
</Books>
---- Version B
<Books>    
 <book id='1' image='C011' name='C# in Depth'/>
 <book id='2' image='C02' name='ASP.NET 2.0'/>
 <book id='3' image='XXXC03' name='XXXLINQ in Action '/>
 <book id='4' image='C04' name='Architecting Applications'/>
<book id='5' image='C05' name='PowerShell in Action'/>
</Books>

以下を返却したい

 ---- Results
 <Books>
  <book id='1' image='C011' name='C# in Depth'/>
  <book id='2' image='C02' name='ASP.NET 2.0'/>
  <book id='3' image='XXXC03' name='XXXLINQ in Action '/>
  <book id='5' image='C05' name='PowerShell in Action'/>
</Books>

これまでの私のコードは次のとおりです。IDに基づいて変更を取得できますが、新しいものは取得できません。また、誰かが1つのステートメントですべてを取得し、再度解析することなく属性も取得できると確信しています。ありがとう

 private void LinqCompareXMLFiles() 
        {
            string oldXML = @"<Books>
     <book id='1' image='C01' name='C# in Depth'/>
     <book id='2' image='C02' name='ASP.NET'/>
     <book id='3' image='C03' name='LINQ in Action '/>
     <book id='4' image='C04' name='Architecting Applications'/>

    </Books>";

            string newXML = @"<Books>
     <book id='1' image='C011' name='C# in Depth'/>
     <book id='2' image='C02' name='ASP.NET 2.0'/>
     <book id='3' image='XXXC03' name='XXXLINQ in Action '/>
     <book id='4' image='C04' name='Architecting Applications'/>
    <book id='5' image='C05' name='PowerShell in Action'/>

    </Books>";

            XDocument xmlOld = XDocument.Parse(oldXML);
            XDocument xmlNew = XDocument.Parse(newXML);

            var res = (from b1 in xmlOld.Descendants("book")
                       from b2 in xmlNew.Descendants("book")
                      let issues = from a1 in b1.Attributes()
                                   join a2 in b2.Attributes()
                                     on a1.Name equals a2.Name
                                   select new
                                   {
                                       Id = a1.Parent.FirstAttribute.Value,
                                       Name = a1.Name,
                                       Value1 = a1.Value,
                                       Value2 = a2.Value
                                   }
                      where issues.Any(i => i.Value1 == i.Value2)
                      from issue in issues
                      where issue.Value1 != issue.Value2
                      select issue);
            var reportXmlItems = (from rx in res select new XElement("book", new XAttribute("id", rx.Id))).Distinct(new MyComparer());

            // This isn't excluding the ids that exist in theold book set because they are different elements I guess and I need to exclude based on the element Id
            var res2 = (from b2 in xmlNew.Descendants("book") select new XElement("book", new XAttribute("id",b2.Attribute("id").Value))).Except(xmlOld.Descendants("book"));

            var res3 = reportXmlItems.Union(res2);

            var reportXml = new XElement("books", res3);
            reportXml.Save(@"c:\test\result.xml");
        }

    public class MyComparer : IEqualityComparer<XElement>
    {
        public bool Equals(XElement x, XElement y)
        {
            return x.Attribute("id").Value == y.Attribute("id").Value;
        }

        public int GetHashCode(XElement obj)
        {
            return obj.Attribute("id").Value.GetHashCode();
        }
    }
4

3 に答える 3

2

自己実装ソリューションに進む前に、xmldiff を確認することをお勧めします。ここで見つけることができるいくつかの参考文献: http://msdn.microsoft.com/en-us/library/aa302294.aspx

于 2013-10-31T18:09:11.260 に答える
0

以下のように、元の質問の宣言的なスタイルで、これをあまり冗長ではなく、もう少し行うことが可能だと思います。

XDocument xdoc = new XDocument(new XElement("Books",
    from newBook in XDocument.Parse(newXML).Descendants("book")
    join oldBook in XDocument.Parse(oldXML).Descendants("book")
        on newBook.Attributes("id").First().Value equals oldBook.Attributes("id").First().Value into oldBooks
    where !oldBooks.Any()
            || newBook.Attributes().Any(a => a.Value != oldBooks.First().Attributes(a.Name).First().Value)
    select newBook));

これにより、要求された回答が得られますが、Linq でよくあることですが、1 行で多くのことを行うと、理解とデバッグが難しくなる可能性があります。id でグループ結合を行い、一致する古いアイテムがないか、一致するアイテムに異なる属性値がある新しいアイテムを選択することに注意してください。

于 2014-10-21T18:46:28.550 に答える