如何使用C#中的LINQ比较两个XML?

7

I want to compare 2 XML files.

My xml1 is:

<ROOT><NODE><BOOK><ID>1234</ID><NAME isbn="dafdfad">Numbers: Language of Science</NAME><AUTHOR>Tobias Dantzig</AUTHOR></BOOK></NODE></ROOT>

我有另一个来自数据库的XML文件,它是:

<Book xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Id>12345</Id><Name isbn="31231223">Numbers: Language of Science</Name><Author>Tobias Dantzig</Author></Book>

我希望比较XML1中的 "BOOK" 节点和来自数据库XML的 "Book" 节点。
  • 我在XML中有一个命名空间,它是从数据库中获取的。
  • 节点名称为混合大小写。
我想逐个比较这两个XML文件的节点文本和属性值。
我使用C#,想知道是否可以使用LINQ实现此操作。
非常感谢您的帮助。
注:我已经搜索了类似的帖子,但没有找到我真正需要的内容。
提前致谢!
祝好, Karthik

假设你比较它们,比较的结果是什么? - Saeed Amiri
我想要的是,如果值不同,那么我想将它们存储在xml1的属性中。例如:如果ID值不同,则在比较后我想要像这样存储:<ID isChanged="true">1234</ID>。 - KK99
1
+1,这个通用问题很有趣。虽然我不认为它是LINQ的一个好应用,但是我想到的工具是IEnumerable<T>.Except,它只对输出在一个/另一个集合中缺失的节点有用。您还需要编写自定义比较(不确定Except是否支持),以及树展平器。结果不会在树中,因此您可能需要进行一些字典操作,以便将差异结果返回到树中。您是否关心是否有通用解决方案? - Merlyn Morgan-Graham
2个回答

5
在XML中,大小写和命名空间非常重要,而空格和属性顺序并不重要(直接字符串比较是错误的)。
所以,在我看来,你应该解析它;也许可以使用XmlSerializer,但是(如你所指出的),这两个都可以使用LINQ-to-XML轻松解析:
string xml1 = @"<ROOT><NODE><BOOK><ID>1234</ID><NAME isbn=""dafdfad"">Numbers: Language of Science</NAME><AUTHOR>Tobias Dantzig</AUTHOR></BOOK></NODE></ROOT>";

var book1 = (from book in XElement.Parse(xml1).Elements("NODE").Elements("BOOK")
            let nameEl = book.Element("NAME")
            select new
            {
                Id = (int)book.Element("ID"),
                Name = nameEl.Value,
                Isbn = (string)nameEl.Attribute("isbn"),
                Author = (string)book.Element("AUTHOR")
            }).Single();

string xml2 = @"<Book xmlns:rdf=""http://www.w3.org/1999/02/22-rdf-syntax-ns#""><Id>12345</Id><Name isbn=""31231223"">Numbers: Language of Science</Name><Author>Tobias Dantzig</Author></Book>";
var el = XElement.Parse(xml2);
var book2 = new
{
    Id = (int)el.Element("Id"),
    Name = el.Element("Name").Value,
    Isbn = el.Element("Name").Attribute("isbn"),
    Author = el.Element("Author")
};

然后就只需要比较这些值。


另一种方法是使用类似xslt的工具预处理其中一个文件,使其与另一个文件的预期布局匹配,这样就可以共享解析代码。这取决于您是否已经熟悉xslt。


非常感谢。我会尝试这个方法。由于我的原始XML节点数量更多,而且我不想硬编码节点名称,所以我在想是否有更简单的方法。 - KK99
@Karthik,XSLT 可能对将元素名称转换为大写有用,但这个要求有点...不寻常。 - Marc Gravell
是的,没错 :-) 我担心的是将来可能会添加XML节点名称,我不希望我的代码因此而改变。我也会检查XSLT。 - KK99

-2

可以很容易地使用Linq to XML或甚至简单的Xml DOM来完成。 虽然我会勇敢地使用正则表达式来完成。 一个正则表达式找到所有的书,再用一两个拆解每个记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接