public XTree(XmlDocument document) { Document = document; Root = XNode.Build(document.DocumentElement, null); }
public static XNode Build(XmlNode node, XNode parent) { if (node.NodeType == XmlNodeType.Attribute) { var xnode = new XNode(node, parent); xnode.Name = node.Name.ToLowerInvariant(); var name = "@" + xnode.Name; xnode.Hash = Murmur3Hasher.HashString(name + "/" + (node.Value ?? string.Empty)); return(xnode); } else if (node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA) { var xnode = new XNode(node, parent); xnode.Name = "#text"; xnode.Hash = Murmur3Hasher.HashString(xnode.Name + "/" + (node.Value ?? string.Empty)); return(xnode); } else if (node.NodeType == XmlNodeType.Element) { var xnode = new XNode(node, parent); var name = node.Name.ToLowerInvariant(); xnode.Name = name; var hashes = new List <byte[]>(); hashes.Add(Murmur3Hasher.HashString(name + "/")); // Add attributes var attributes = new List <XNode>(); for (var i = 0; i < node.Attributes.Count; i++) { var child = XNode.Build(node.Attributes[i], xnode); if (child != null) { hashes.Add(child.Hash); attributes.Add(child); } } xnode.Attributes = attributes.ToArray(); // Add child elements and text nodes var children = new List <XNode>(); var elements = new List <XNode>(); var texts = new List <XNode>(); for (var i = 0; i < node.ChildNodes.Count; i++) { var child = XNode.Build(node.ChildNodes[i], xnode); if (child != null) { hashes.Add(child.Hash); children.Add(child); if (child.IsElement()) { elements.Add(child); } else { texts.Add(child); } } } xnode.Children = children.ToArray(); xnode.Elements = elements.ToArray(); xnode.Texts = texts.ToArray(); // Sort and concatenate child hashes and then compute the hash var joined = ConcatAll(hashes.OrderBy(h => h, ByteArrayComparer.Instance) .ToList(), Murmur3Hasher.OUTPUT_LENGTH); xnode.Hash = Murmur3Hasher.HashBytes(joined); return(xnode); } return(null); }