使用它们的字符串表示来比较两个 XML 文档并不是一个好主意。虽然这两个文档可能是等价的,但它们仍然可能有许多词汇差异,其中包括:
- 不同的前缀绑定到同一个命名空间。
- 使用/不使用 CDATA 部分
- 表示/不表示为字符串继承的命名空间节点
- 使用引号与撇号
- 使用与不使用字符实体。
- ..., ETC。
我会推荐一种更好的方法——有很多xmldiff 工具。您还可以根据我对这个问题的回答构建自己的 XML 比较工具(就像我为自己所做的那样)。
更新:
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 创建的 Navigator 显然不属于此类别,因此会观察到报告的问题。
解决方案:
改变:
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);
}
}
}
}