【问题标题】:Xml Comparison in C#C# 中的 XML 比较
【发布时间】:2009-04-27 16:42:52
【问题描述】:

我正在尝试使用 C# 代码比较两个 Xml 文件。 我想忽略 Xml 语法差异(即前缀名称)。 为此,我正在使用 Microsoft 的 XML Diff and Patch C# API。 它适用于某些 Xml,但我找不到将其配置为与以下两个 Xml 一起使用的方法:

XML A:

<root xmlns:ns="http://myNs">
  <ns:child>1</ns:child>
</root>

XML B:

<root>
  <child xmlns="http://myNs">1</child>
</root>

我的问题是:

  1. 我认为这两个 xml 在语义上是相等的(或同构)吗?
  2. 能否配置 Microsoft 的 XML Diff and Patch API 以支持它?
  3. 还有其他 C# 实用程序可以解决这个问题吗?

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    文档是同构的,如下面的程序所示。我想如果你使用XmlDiffOptions.IgnoreNamespacesXmlDiffOptions.IgnorePrefixes来配置Microsoft.XmlDiffPatch.XmlDiff,你会得到你想要的结果。

    using System.Linq;
    using System.Xml.Linq;
    namespace SO_794331
    {
        class Program
        {
            static void Main(string[] args)
            {
                var docA = XDocument.Parse(
                    @"<root xmlns:ns=""http://myNs""><ns:child>1</ns:child></root>");
                var docB = XDocument.Parse(
                    @"<root><child xmlns=""http://myNs"">1</child></root>");
    
                var rootNameA = docA.Root.Name;
                var rootNameB = docB.Root.Name;
                var equalRootNames = rootNameB.Equals(rootNameA);
    
                var descendantsA = docA.Root.Descendants();
                var descendantsB = docB.Root.Descendants();
                for (int i = 0; i < descendantsA.Count(); i++)
                {
                    var descendantA = descendantsA.ElementAt(i);
                    var descendantB = descendantsB.ElementAt(i);
                    var equalChildNames = descendantA.Name.Equals(descendantB.Name);
    
                    var valueA = descendantA.Value;
                    var valueB = descendantB.Value;
                    var equalValues = valueA.Equals(valueB);
                }
            }
        }
    }
    

    【讨论】:

    • IgnoreNamespaces 对我不利 - 我认为具有不同命名空间的文档在语义上是不同的。
    • 我明白,但似乎 XML Patch&Diff 在比较时确实考虑了命名空间,即使使用 IgnoreNamespaces 也是如此。我用两个文档 对此进行了测试。 Diff&Patch 认为它们是不同的。不幸的是,我现在没有拿到代码,所以我无法 100% 确认。
    • 我之前评论中的 A 和 B 本来是两个 url,但它们被转换为链接......
    • 当我尝试它时,我发现它们是平等的
    • 我得到了和你一样的结果。我想我之前犯了一个错误。继续调查...
    【解决方案2】:

    我知道您关注的不是单元测试,但XMLUnit 可以比较两个 XML 文件,我认为它能够解决您的示例。也许你可以看看代码找出你的解决方案。

    【讨论】:

    • 其实我的重点是单元测试。然而 XMLUnit 在 .Net 中似乎也有类似的限制。它实际上适用于上述 Xml,但稍有变化就破坏了它。
    【解决方案3】:

    我在 XML 和 .NET Framework MSDN 论坛中有 an answer by Martin Honnen。 简而言之,他建议使用 XQuery 1.0 的 deep-equal 函数并提供一些 C# 实现。似乎有效。

    【讨论】:

      【解决方案4】:

      从每个 xml 文件加载 XmlDocument 实例并比较 XML DOM 可能是一个想法?对每个都进行正确的验证,这应该为您提供比较的共同基础,并且应该允许标准差异报告。甚至可能使用增量更新另一个。

      【讨论】:

      • 这是一个选项 - 但它自己做的事情我认为是一个常见的解决方案的常见问题。
      【解决方案5】:

      这些文档在语义上并不等效。第一个的顶级元素在http://myNS 命名空间中,而第二个的顶级元素在默认命名空间中。

      两个文档的 child 元素是等价的。但文件本身不是。

      编辑:

      xmls:ns='http://myNS'xmlns='http://myNS' 之间存在天壤之别,我似乎忽略了这一点。无论如何,这些文档在语义上是等效的,我只是弄错了。

      【讨论】:

      • 这是不正确的。两个文档的顶级元素都在默认命名空间中。如果声明为 myNs"> 或 myNs">myNs 命名空间中/跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多