XElement.CreateNavigator() 和 XPathDocument().CreateNavigator() 之间的区别

发布于 2024-12-04 05:32:11 字数 500 浏览 2 评论 0原文

以下测试失败。 r1 似乎缺少尖括号,有人知道吗?我想它是某种编码错误?

var nav1 = XElement.Load(stream).CreateNavigator(); 
var nav2 = new XPathDocument(stream).CreateNavigator();

using (var r1 = new StringWriter())
using (var r2 = new StringWriter())
{
  xslt.Transform(nav1, null, r1);
  xslt.Transform(nav2, null, r2);

  r1.ToString().Should().Equal(r2.ToString());
}

据我所知,这里的问题不是语义上等效但词法上不同的 xml,而是 r1 情况下生成的 xml 缺少它的 xml 标签。有趣的是,使用 var nav3 = XElement.Load(stream).CreateReader(); 效果很好。

The following test fails. r1 seems to be missing angle brackets, does anyone know way? I imagine its some sort of encoding error?

var nav1 = XElement.Load(stream).CreateNavigator(); 
var nav2 = new XPathDocument(stream).CreateNavigator();

using (var r1 = new StringWriter())
using (var r2 = new StringWriter())
{
  xslt.Transform(nav1, null, r1);
  xslt.Transform(nav2, null, r2);

  r1.ToString().Should().Equal(r2.ToString());
}

The problem here is not as far as I can tell semantically equivalent but lexically different xml, but that the resulting xml in the r1 case is missing it's xml tags. Interestingly, using var nav3 = XElement.Load(stream).CreateReader(); works fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云雾 2024-12-11 05:32:11

使用字符串表示形式比较两个 XML 文档并不是一个好主意。虽然这两个文档可能是等效的,但它们仍然可能存在许多词汇差异,其中:

  • 绑定到同一名称空间的不同前缀。
  • 使用/不使用 CDATA 部分
  • 表示/不表示为字符串继承的命名空间节点
  • 使用引号与撇号
  • 使用与不使用字符实体。
  • ...等等。

我会推荐一种更好的方法——有很多 xmldiff 工具。您还可以根据我对 这个问题

更新

OP澄清后:

“据我所知,这里的问题并不是语义上等价的
但词法上不同的 xml,但 r1 情况下生成的 xml
缺少它的 xml 标签”

我调查并得出以下结论

XslCompiledTransform.Transform(IXPathNavigable, XsltArgumentList, Stream) 使用 XmlDocument 或 XPathDocument 作为第一个参数, MSDN 文档中进行了描述

Parameters     
   inputType: System.Xml.XPath.IXPathNavigable An object    
              implementing the IXPathNavigable interface. In the Microsoft .NET Framework, this
              can  be either an XmlNode (typically an XmlDocument), or 
              an XPathDocument containing the data to be transformed.

由于从 XElement 创建的导航器显然不属于此类别,因此观察到报告的问题。

解决方案

更改:

var nav1 = XElement.Load(stream).CreateNavigator();

到:

var nav1 = XDocument.Load(stream).CreateNavigator();

      

这里是已验证可以按预期工作的完整代码

using System.IO;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Xsl;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestLINQ_Xml
{
    class Program
    {
        static void Main(string[] args)
        {
            test();
        }

        static void test()
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(@"C:\temp\delete\XSLT.xsl");

            FileStream stream = 
              new FileStream(@"C:\temp\delete\sourceXML.xml", FileMode.Open);

            var xdoc = XDocument.Load(stream);
            var nav1 = xdoc.CreateNavigator();

            stream.Seek(0L, SeekOrigin.Begin);
            var nav2 = new XPathDocument(stream).CreateNavigator(); 

            using (var r1 = new StringWriter()) using (var r2 = new StringWriter()) 
            {   xslt.Transform(nav2, null, r1); 
                xslt.Transform(nav1, null, r2); 

                string  res1 = r1.ToString();
                string  res2 = r2.ToString();

                Assert.AreEqual(res1, res2);
            } 
        }
    }
}

Comparing two XML documents using their string representation is not a good idea. While the two documents may be equivalent, they still could have many lexical differences, among them:

  • Different prefixes bound to the same namespace.
  • Use/not use CDATA sections
  • represent/not-represent as strings inherited namespace nodes
  • use quotes vs apostrophes
  • use vs not-use character entities.
  • ..., etc.

I would recommend a better way of doing this -- there are many xmldiff tools. You could also build your own XML comparison tool (as I have done for myself) based on my answer to this question.

UPDATE:

After clarifications from the OP:

"The problem here is not as far as I can tell semantically equivalent
but lexically different xml, but that the resulting xml in the r1 case
is missing it's xml tags"

I investigated and came up with the following conclusion:

The XslCompiledTransform.Transform(IXPathNavigable, XsltArgumentList, Stream) works with either XmlDocument or XPathDocument as the first argument, as is described in the MSDN documentation.

Parameters     
   inputType: System.Xml.XPath.IXPathNavigable An object    
              implementing the IXPathNavigable interface. In the Microsoft .NET Framework, this
              can  be either an XmlNode (typically an XmlDocument), or 
              an XPathDocument containing the data to be transformed.

As the Navigator created from an XElement obviously doesn't fit in this category, the reported problem is observed.

Solution:

Change:

var nav1 = XElement.Load(stream).CreateNavigator();

to:

var nav1 = XDocument.Load(stream).CreateNavigator();

      

Here is complete code that has been verified to work as expected:

using System.IO;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Xsl;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestLINQ_Xml
{
    class Program
    {
        static void Main(string[] args)
        {
            test();
        }

        static void test()
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(@"C:\temp\delete\XSLT.xsl");

            FileStream stream = 
              new FileStream(@"C:\temp\delete\sourceXML.xml", FileMode.Open);

            var xdoc = XDocument.Load(stream);
            var nav1 = xdoc.CreateNavigator();

            stream.Seek(0L, SeekOrigin.Begin);
            var nav2 = new XPathDocument(stream).CreateNavigator(); 

            using (var r1 = new StringWriter()) using (var r2 = new StringWriter()) 
            {   xslt.Transform(nav2, null, r1); 
                xslt.Transform(nav1, null, r2); 

                string  res1 = r1.ToString();
                string  res2 = r2.ToString();

                Assert.AreEqual(res1, res2);
            } 
        }
    }
}
献世佛 2024-12-11 05:32:11

我重现了你的结果。我的输入 XML 包含 2 个命名空间,在输出 XML 中,命名空间以不同的顺序定义。您可以逐字节检查输出并找到差异。

I reproduced your result. My input XML contains 2 namespaces, in output XMLs namespaces are defined in different order. You can check your output byte by byte and find differences.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文