// This is a helper function for WriteResult. It gets the Xml representation of the different node we wants // to write out and all it's children. private string GetNodeText(XmlDiffNode diffNode, DiffType result) { string text; switch (diffNode.NodeType) { case XmlDiffNodeType.Element: if (result == DiffType.SourceExtra || result == DiffType.TargetExtra) { return(diffNode.OuterXml); } StringWriter str = new StringWriter(); XmlTextWriter writer = new XmlTextWriter(str); XmlDiffElement diffElem = diffNode as XmlDiffElement; Debug.Assert(diffNode != null); writer.WriteStartElement(diffElem.Prefix, diffElem.LocalName, diffElem.NamespaceURI); XmlDiffAttribute diffAttr = diffElem.FirstAttribute; while (diffAttr != null) { writer.WriteAttributeString(diffAttr.Prefix, diffAttr.LocalName, diffAttr.NamespaceURI, diffAttr.Value); diffAttr = (XmlDiffAttribute)diffAttr.NextSibling; } if (diffElem is XmlDiffEmptyElement) { writer.WriteEndElement(); text = str.ToString(); } else { text = str.ToString(); text += ">"; } writer.Close(); break; case XmlDiffNodeType.CData: text = ((XmlDiffCharacterData)diffNode).Value; break; default: text = diffNode.OuterXml; break; } return(text); }
// This function is used to compare the attributes of an element node according to the options set by the user. private bool CompareAttributes(XmlDiffElement sourceElem, XmlDiffElement targetElem) { Debug.Assert(sourceElem != null); Debug.Assert(targetElem != null); if (sourceElem.AttributeCount != targetElem.AttributeCount) { return(false); } if (sourceElem.AttributeCount == 0) { return(true); } XmlDiffAttribute sourceAttr = sourceElem.FirstAttribute; XmlDiffAttribute targetAttr = targetElem.FirstAttribute; while (sourceAttr != null && targetAttr != null) { if (!IgnoreNS) { if (sourceAttr.NamespaceURI != targetAttr.NamespaceURI) { return(false); } } if (!IgnorePrefix) { if (sourceAttr.Prefix != targetAttr.Prefix) { return(false); } } if (sourceAttr.LocalName != targetAttr.LocalName || sourceAttr.Value != targetAttr.Value) { return(false); } sourceAttr = (XmlDiffAttribute)(sourceAttr.NextSibling); targetAttr = (XmlDiffAttribute)(targetAttr.NextSibling); } return(true); }
// This function is used to compare the attributes of an element node according to the options set by the user. private bool CompareAttributes(XmlDiffElement sourceElem, XmlDiffElement targetElem) { Debug.Assert(sourceElem != null); Debug.Assert(targetElem != null); if (sourceElem.AttributeCount != targetElem.AttributeCount) { return(false); } if (sourceElem.AttributeCount == 0) { return(true); } XmlDiffAttribute sourceAttr = sourceElem.FirstAttribute; XmlDiffAttribute targetAttr = targetElem.FirstAttribute; const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/"; if (!IgnoreAttributeOrder) { while (sourceAttr != null && targetAttr != null) { if (!IgnoreNS) { if (sourceAttr.NamespaceURI != targetAttr.NamespaceURI) { return(false); } } if (!IgnorePrefix) { if (sourceAttr.Prefix != targetAttr.Prefix) { return(false); } } if (sourceAttr.NamespaceURI == xmlnsNamespace && targetAttr.NamespaceURI == xmlnsNamespace) { if (!IgnorePrefix && (sourceAttr.LocalName != targetAttr.LocalName)) { return(false); } if (!IgnoreNS && (sourceAttr.Value != targetAttr.Value)) { return(false); } } else { if (sourceAttr.LocalName != targetAttr.LocalName) { return(false); } if (sourceAttr.Value != targetAttr.Value) { if (ParseAttributeValuesAsQName) { if (sourceAttr.ValueAsQName != null) { if (!sourceAttr.ValueAsQName.Equals(targetAttr.ValueAsQName)) { return(false); } } else { if (targetAttr.ValueAsQName != null) { return(false); } } } else { return(false); } } } sourceAttr = (XmlDiffAttribute)(sourceAttr.NextSibling); targetAttr = (XmlDiffAttribute)(targetAttr.NextSibling); } } else { Hashtable sourceAttributeMap = new Hashtable(); Hashtable targetAttributeMap = new Hashtable(); while (sourceAttr != null && targetAttr != null) { if (IgnorePrefix && sourceAttr.NamespaceURI == xmlnsNamespace) { // do nothing } else { string localNameAndNamespace = sourceAttr.LocalName + "<&&>" + sourceAttr.NamespaceURI; sourceAttributeMap.Add(localNameAndNamespace, sourceAttr); } if (IgnorePrefix && targetAttr.NamespaceURI == xmlnsNamespace) { // do nothing } else { string localNameAndNamespace = targetAttr.LocalName + "<&&>" + targetAttr.NamespaceURI; targetAttributeMap.Add(localNameAndNamespace, targetAttr); } sourceAttr = (XmlDiffAttribute)(sourceAttr.NextSibling); targetAttr = (XmlDiffAttribute)(targetAttr.NextSibling); } if (sourceAttributeMap.Count != targetAttributeMap.Count) { return(false); } foreach (string sourceKey in sourceAttributeMap.Keys) { if (!targetAttributeMap.ContainsKey(sourceKey)) { return(false); } sourceAttr = (XmlDiffAttribute)sourceAttributeMap[sourceKey]; targetAttr = (XmlDiffAttribute)targetAttributeMap[sourceKey]; if (!IgnorePrefix) { if (sourceAttr.Prefix != targetAttr.Prefix) { return(false); } } if (sourceAttr.Value != targetAttr.Value) { if (ParseAttributeValuesAsQName) { if (sourceAttr.ValueAsQName != null) { if (!sourceAttr.ValueAsQName.Equals(targetAttr.ValueAsQName)) { return(false); } } else { if (targetAttr.ValueAsQName != null) { return(false); } } } else { return(false); } } } } return(true); }
// 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); }
// This function is being called recursively to compare the children of a certain node. // When calling this function the navigator should be pointing at the parent node whose children // we wants to compare and return the navigator back to the same node before exiting from it. private bool CompareChildren(XmlDiffNode sourceNode, XmlDiffNode targetNode) { XmlDiffNode sourceChild = sourceNode.FirstChild; XmlDiffNode targetChild = targetNode.FirstChild; bool flag = true; bool tempFlag = true; DiffType result; // Loop to compare all the child elements of the parent node while (sourceChild != null || targetChild != null) { if (sourceChild != null) { if (targetChild != null) { // Both Source and Target Read successful if ((result = CompareNodes(sourceChild, targetChild)) == DiffType.Success) { // Child nodes compared successfully, write out the result WriteResult(sourceChild, targetChild, DiffType.Success); // Check whether this Node has Children, if it does call CompareChildren recursively if (sourceChild.FirstChild != null) { tempFlag = CompareChildren(sourceChild, targetChild); } else if (targetChild.FirstChild != null) { WriteResult(null, targetChild, DiffType.TargetExtra); tempFlag = false; } // set the compare flag flag = (flag && tempFlag); // Writing out End Element to the result if (sourceChild.NodeType == XmlDiffNodeType.Element && !(sourceChild is XmlDiffEmptyElement)) { XmlDiffElement sourceElem = sourceChild as XmlDiffElement; XmlDiffElement targetElem = targetChild as XmlDiffElement; Debug.Assert(sourceElem != null); Debug.Assert(targetElem != null); if (!DontWriteMatchingNodesToOutput && !DontWriteAnythingToOutput) { _Writer.WriteStartElement(string.Empty, "Node", string.Empty); _Writer.WriteAttributeString(string.Empty, "SourceLineNum", string.Empty, sourceElem.EndLineNumber.ToString()); _Writer.WriteAttributeString(string.Empty, "SourceLinePos", string.Empty, sourceElem.EndLinePosition.ToString()); _Writer.WriteAttributeString(string.Empty, "TargetLineNum", string.Empty, targetElem.EndLineNumber.ToString()); _Writer.WriteAttributeString(string.Empty, "TargetLinePos", string.Empty, targetElem.EndLinePosition.ToString()); _Writer.WriteStartElement(string.Empty, "Diff", string.Empty); _Writer.WriteEndElement(); _Writer.WriteStartElement(string.Empty, "Lexical-equal", string.Empty); _Writer.WriteCData("</" + sourceElem.Name + ">"); _Writer.WriteEndElement(); _Writer.WriteEndElement(); } } // Move to Next child sourceChild = sourceChild.NextSibling; targetChild = targetChild.NextSibling; } else { // Child nodes not matched, start the recovery process bool recoveryFlag = false; // Try to match the source node with the target nodes at the same level XmlDiffNode backupTargetChild = targetChild.NextSibling; while (!recoveryFlag && backupTargetChild != null) { if (CompareNodes(sourceChild, backupTargetChild) == DiffType.Success) { recoveryFlag = true; do { WriteResult(null, targetChild, DiffType.TargetExtra); targetChild = targetChild.NextSibling; } while (targetChild != backupTargetChild); break; } backupTargetChild = backupTargetChild.NextSibling; } // If not recovered, try to match the target node with the source nodes at the same level if (!recoveryFlag) { XmlDiffNode backupSourceChild = sourceChild.NextSibling; while (!recoveryFlag && backupSourceChild != null) { if (CompareNodes(backupSourceChild, targetChild) == DiffType.Success) { recoveryFlag = true; do { WriteResult(sourceChild, null, DiffType.SourceExtra); sourceChild = sourceChild.NextSibling; } while (sourceChild != backupSourceChild); break; } backupSourceChild = backupSourceChild.NextSibling; } } // If still not recovered, write both of them as different nodes and move on if (!recoveryFlag) { WriteResult(sourceChild, targetChild, result); // Check whether this Node has Children, if it does call CompareChildren recursively if (sourceChild.FirstChild != null) { tempFlag = CompareChildren(sourceChild, targetChild); } else if (targetChild.FirstChild != null) { WriteResult(null, targetChild, DiffType.TargetExtra); tempFlag = false; } // Writing out End Element to the result bool bSourceNonEmpElemEnd = (sourceChild.NodeType == XmlDiffNodeType.Element && !(sourceChild is XmlDiffEmptyElement)); bool bTargetNonEmpElemEnd = (targetChild.NodeType == XmlDiffNodeType.Element && !(targetChild is XmlDiffEmptyElement)); if (bSourceNonEmpElemEnd || bTargetNonEmpElemEnd) { XmlDiffElement sourceElem = sourceChild as XmlDiffElement; XmlDiffElement targetElem = targetChild as XmlDiffElement; if (!DontWriteAnythingToOutput) { _Writer.WriteStartElement(string.Empty, "Node", string.Empty); _Writer.WriteAttributeString(string.Empty, "SourceLineNum", string.Empty, (sourceElem != null) ? sourceElem.EndLineNumber.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "SourceLinePos", string.Empty, (sourceElem != null) ? sourceElem.EndLinePosition.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "TargetLineNum", string.Empty, (targetElem != null) ? targetElem.EndLineNumber.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "TargetLinePos", string.Empty, (targetElem != null) ? targetElem.EndLineNumber.ToString() : "-1"); _Writer.WriteStartElement(string.Empty, "Diff", string.Empty); _Writer.WriteAttributeString(string.Empty, "DiffType", string.Empty, GetDiffType(result)); if (bSourceNonEmpElemEnd) { _Writer.WriteStartElement(string.Empty, "File1", string.Empty); _Writer.WriteCData("</" + sourceElem.Name + ">"); _Writer.WriteEndElement(); } if (bTargetNonEmpElemEnd) { _Writer.WriteStartElement(string.Empty, "File2", string.Empty); _Writer.WriteCData("</" + targetElem.Name + ">"); _Writer.WriteEndElement(); } _Writer.WriteEndElement(); _Writer.WriteStartElement(string.Empty, "Lexical-equal", string.Empty); _Writer.WriteEndElement(); _Writer.WriteEndElement(); } } sourceChild = sourceChild.NextSibling; targetChild = targetChild.NextSibling; } flag = false; } } else { // SourceRead NOT NULL targetRead is NULL WriteResult(sourceChild, null, DiffType.SourceExtra); flag = false; sourceChild = sourceChild.NextSibling; } } else if (targetChild != null) { // SourceRead is NULL and targetRead is NOT NULL WriteResult(null, targetChild, DiffType.TargetExtra); flag = false; targetChild = targetChild.NextSibling; } else { //Both SourceRead and TargetRead is NULL Debug.Assert(false, "Impossible Situation for comparison"); } } return(flag); }
// This function is used to compare the attributes of an element node according to the options set by the user. private bool CompareAttributes(XmlDiffElement sourceElem, XmlDiffElement targetElem) { Debug.Assert(sourceElem != null); Debug.Assert(targetElem != null); if (sourceElem.AttributeCount != targetElem.AttributeCount) return false; if (sourceElem.AttributeCount == 0) return true; XmlDiffAttribute sourceAttr = sourceElem.FirstAttribute; XmlDiffAttribute targetAttr = targetElem.FirstAttribute; while (sourceAttr != null && targetAttr != null) { if (!IgnoreNS) { if (sourceAttr.NamespaceURI != targetAttr.NamespaceURI) return false; } if (!IgnorePrefix) { if (sourceAttr.Prefix != targetAttr.Prefix) return false; } if (sourceAttr.LocalName != targetAttr.LocalName || sourceAttr.Value != targetAttr.Value) return false; sourceAttr = (XmlDiffAttribute)(sourceAttr.NextSibling); targetAttr = (XmlDiffAttribute)(targetAttr.NextSibling); } return true; }