/// <summary> /// Combines multiple adjacent text nodes into a single node. /// Sometimes the binary reader/writer will break text nodes in multiple /// nodes; i.e., if the user calls /// <code>writer.WriteString("foo"); writer.WriteString("bar")</code> /// on the writer and then iterate calling reader.Read() on the document, the binary /// reader will report two text nodes ("foo", "bar"), while the /// other readers will report a single text node ("foobar") – notice that /// this is not a problem; calling ReadString, or Read[Element]ContentAsString in /// all readers will return "foobar". /// </summary> /// <param name="node">the node to be normalized. Any siblings of /// type XmlDiffCharacterData will be removed, with their values appended /// to the value of this node</param> private void DoConcatenateAdjacentTextNodes(XmlDiffCharacterData node) { if (node.NextSibling == null) { return; } if (!(node.NextSibling is XmlDiffCharacterData)) { return; } StringBuilder sb = new StringBuilder(); sb.Append(node.Value); XmlDiffCharacterData nextNode = (node.NextSibling as XmlDiffCharacterData); while (nextNode != null) { sb.Append(nextNode.Value); XmlDiffCharacterData curNextNode = nextNode; nextNode = (nextNode.NextSibling as XmlDiffCharacterData); curNextNode.ParentNode.DeleteChild(curNextNode); } node.Value = sb.ToString(); }
// This function compares the two nodes passed to it, depending upon the options set by the user. private DiffType CompareNodes(XmlDiffNode sourceNode, XmlDiffNode targetNode) { if (sourceNode.NodeType != targetNode.NodeType) { return(DiffType.NodeType); } switch (sourceNode.NodeType) { case XmlDiffNodeType.Element: XmlDiffElement sourceElem = sourceNode as XmlDiffElement; XmlDiffElement targetElem = targetNode as XmlDiffElement; Debug.Assert(sourceElem != null); Debug.Assert(targetElem != null); if (!IgnoreNS) { if (sourceElem.NamespaceURI != targetElem.NamespaceURI) { return(DiffType.NS); } } if (!IgnorePrefix) { if (sourceElem.Prefix != targetElem.Prefix) { return(DiffType.Prefix); } } if (sourceElem.LocalName != targetElem.LocalName) { return(DiffType.Element); } if (!IgnoreEmptyElement) { if ((sourceElem is XmlDiffEmptyElement) != (targetElem is XmlDiffEmptyElement)) { return(DiffType.Element); } } if (!CompareAttributes(sourceElem, targetElem)) { return(DiffType.Attribute); } break; case XmlDiffNodeType.Text: case XmlDiffNodeType.Comment: case XmlDiffNodeType.WS: XmlDiffCharacterData sourceText = sourceNode as XmlDiffCharacterData; XmlDiffCharacterData targetText = targetNode as XmlDiffCharacterData; Debug.Assert(sourceText != null); Debug.Assert(targetText != null); if (ConcatenateAdjacentTextNodes) { DoConcatenateAdjacentTextNodes(sourceText); DoConcatenateAdjacentTextNodes(targetText); } if (IgnoreWhitespace) { if (sourceText.Value.Trim() == targetText.Value.Trim()) { return(DiffType.Success); } } else { if (sourceText.Value == targetText.Value) { return(DiffType.Success); } } if (sourceText.NodeType == XmlDiffNodeType.Text || sourceText.NodeType == XmlDiffNodeType.WS) //should ws nodes also as text nodes??? { return(DiffType.Text); } else if (sourceText.NodeType == XmlDiffNodeType.Comment) { return(DiffType.Comment); } else if (sourceText.NodeType == XmlDiffNodeType.CData) { return(DiffType.CData); } else { return(DiffType.None); } case XmlDiffNodeType.PI: XmlDiffProcessingInstruction sourcePI = sourceNode as XmlDiffProcessingInstruction; XmlDiffProcessingInstruction targetPI = targetNode as XmlDiffProcessingInstruction; Debug.Assert(sourcePI != null); Debug.Assert(targetPI != null); if (sourcePI.Name != targetPI.Name || sourcePI.Value != targetPI.Value) { return(DiffType.PI); } break; default: break; } return(DiffType.Success); }