5 // Copyright 2007 Novell (http://www.novell.com)
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System.Collections;
29 using System.Collections.Generic;
31 using XPI = System.Xml.Linq.XProcessingInstruction;
33 namespace System.Xml.Linq
35 public sealed class XNodeEqualityComparer : IEqualityComparer, IEqualityComparer<XNode>
37 public XNodeEqualityComparer ()
41 public bool Equals (XNode x, XNode y)
47 //throw new NotImplementedException ();
48 if (x.NodeType != y.NodeType)
51 case XmlNodeType.Document:
52 XDocument doc1 = (XDocument) x;
53 XDocument doc2 = (XDocument) y;
54 if (!Equals (doc1.Declaration, doc2.Declaration))
56 IEnumerator<XNode> id2 = doc2.Nodes ().GetEnumerator ();
57 foreach (XNode n in doc1.Nodes ()) {
60 if (!Equals (n, id2.Current))
63 return !id2.MoveNext ();
64 case XmlNodeType.Element:
65 XElement e1 = (XElement) x;
66 XElement e2 = (XElement) y;
67 if (e1.Name != e2.Name)
69 IEnumerator<XAttribute> ia2 = e2.Attributes ().GetEnumerator ();
70 foreach (XAttribute n in e1.Attributes ()) {
73 if (!Equals (n, ia2.Current))
78 IEnumerator<XNode> ie2 = e2.Nodes ().GetEnumerator ();
79 foreach (XNode n in e1.Nodes ()) {
82 if (!Equals (n, ie2.Current))
85 return !ie2.MoveNext ();
86 case XmlNodeType.Comment:
87 XComment c1 = (XComment) x;
88 XComment c2 = (XComment) y;
89 return c1.Value == c2.Value;
90 case XmlNodeType.ProcessingInstruction:
93 return p1.Target == p2.Target && p1.Data == p2.Data;
94 case XmlNodeType.DocumentType:
95 XDocumentType d1 = (XDocumentType) x;
96 XDocumentType d2 = (XDocumentType) y;
97 return d1.Name == d2.Name &&
98 d1.PublicId == d2.PublicId &&
99 d1.SystemId == d2.SystemId &&
100 d1.InternalSubset == d2.InternalSubset;
101 case XmlNodeType.Text:
102 return ((XText) x).Value == ((XText) y).Value;
104 throw new Exception ("INTERNAL ERROR: should not happen");
107 bool Equals (XAttribute a1, XAttribute a2)
113 return a1.Name == a2.Name && a1.Value == a2.Value;
116 bool Equals (XDeclaration d1, XDeclaration d2)
122 return d1.Version == d2.Version &&
123 d1.Encoding == d2.Encoding &&
124 d1.Standalone == d2.Standalone;
127 bool IEqualityComparer.Equals (object n1, object n2)
129 return Equals ((XNode) n1, (XNode) n2);
132 int GetHashCode (XDeclaration d)
136 return (d.Version.GetHashCode () << 7) ^
137 (d.Encoding.GetHashCode () << 6) ^
138 d.Standalone.GetHashCode ();
141 public int GetHashCode (XNode obj)
145 int h = ((int) obj.NodeType << 6);
146 switch (obj.NodeType) {
147 case XmlNodeType.Document:
148 XDocument doc = (XDocument) obj;
149 h = h ^ GetHashCode (doc.Declaration);
150 foreach (XNode n in doc.Nodes ())
151 h = h ^ (n.GetHashCode () << 5);
153 case XmlNodeType.Element:
154 XElement el = (XElement) obj;
155 h = h ^ (el.Name.GetHashCode () << 3);
156 foreach (XAttribute a in el.Attributes ())
157 h = h ^ (a.GetHashCode () << 7);
158 foreach (XNode n in el.Nodes ())
159 h = h ^ (n.GetHashCode () << 6);
161 case XmlNodeType.Comment:
162 h = h ^ ((XComment) obj).Value.GetHashCode ();
164 case XmlNodeType.ProcessingInstruction:
166 h = h ^ ((pi.Target.GetHashCode () << 6) + pi.Data.GetHashCode ());
168 case XmlNodeType.DocumentType:
169 XDocumentType dtd = (XDocumentType) obj;
170 h = h ^ (dtd.Name.GetHashCode () << 7) ^
171 (dtd.PublicId.GetHashCode () << 6) ^
172 (dtd.SystemId.GetHashCode () << 5) ^
173 (dtd.InternalSubset.GetHashCode () << 4);
175 case XmlNodeType.Text:
176 h = h ^ (((XText) obj).GetHashCode ());
182 int IEqualityComparer.GetHashCode (object obj)
184 return GetHashCode ((XNode) obj);