XNode.DeepEquals unexpectedly returns false
Asked Answered
D

2

9

Using XNode.DeepEquals() to compare xml elements, it unexpectedly returns false on two xml documents that I think should be equivalent.

Example

var xmlFromString = XDocument.Parse("<someXml xmlns=\"someNamespace\"/>");
var xmlDirect = new XDocument(new XElement(
  XNamespace.Get("someNamespace") + "someXml"));

Console.WriteLine(xmlFromString.ToString());
Console.WriteLine(xmlDirect.ToString());
Console.WriteLine(XNode.DeepEquals(xmlFromString, xmlDirect));
Console.WriteLine(xmlFromString.ToString() == xmlDirect.ToString());

Output

<someXml xmlns="someNamespace" />
<someXml xmlns="someNamespace" />
False
True

The strings are considered equal, but the XML trees are not. Why?

Dolor answered 11/6, 2014 at 7:7 Comment(3)
Interestingly, DeepEquals reports false just for the root element, too... so it's not a document declaration issue, for example.Weekend
No, already tried that ;-). But if the namespace is removed it correctly reports true.Dolor
I have come to the conclusion that DeepEquals() is totally not applicable for comparison. For example, it differs <node></node> and <node />. This is ridiculous.Kirit
W
5

I've worked out what the difference is, but not why it's different.

In the first form, you have an xmlns attribute. In the second form, you don't - not in terms of what Attributes() returns. If you explicitly construct an XAttribute, DeepEquals will return true:

var xmlDirect = new XDocument(new XElement(
  XNamespace.Get("someNamespace") + "someXml",
  new XAttribute("xmlns", "someNamespace")));

It's as if the namespace only counts as an attribute when converting the tree to a text representation, basically.

Weekend answered 11/6, 2014 at 7:15 Comment(3)
Interesting. Looks like a bug in DeepEquals to me. A workaround then is to bounce the constructed xml over a string: XNode.DeepEquals(xmlFromString, XDocument.Parse(xmlDirect.ToString()) returns true.Dolor
@AndersAbel: I can't see that it would be a bug in DeepEquals - it's behaving as documented, in that the two elements have different numbers of attributes. If anything, it's a bug in either parse (which perhaps shouldn't include the attribute) or XElement construction (which perhaps should). You've got detectably-different trees though, so it's fair for DeepEquals to return false.Weekend
You're right. DeepEquals isn't to blame. But XElement.ToString() and XDocument.Parse should behave consistently IMHO and either treat xmlns as a real attribute or not.Dolor
T
0

After parsing you get a XDocument. Try to retrive the Node to use it in DeepEqual:

var xmlFromString = XDocument.Parse("<someXml xmlns="someNamespace"/>").Root;

This solved the problem for me.

Tessellated answered 25/3, 2021 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.