internal XmlDiffParentNode(int position) : base(position) { this._firstChildNode = (XmlDiffNode)null; this._nodesCount = 1; this._elementChildrenOnly = true; this._bDefinesNamespaces = false; this._hashValue = 0UL; }
// 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); }
static void MakeResult(XmlDiffNode xmlDiffNode, List <ResultDto> resultDtos, ResultDto parent = null) { string fromValue = string.Empty; string toValue = string.Empty; SplitDescription(xmlDiffNode.Description, out fromValue, out toValue); var result = new ResultDto { Id = Guid.NewGuid(), XPath = xmlDiffNode.XPath, Description = xmlDiffNode.Description, DiffType = xmlDiffNode.DiffType.ToString(), DiffId = xmlDiffNode.DiffId, NodeType = xmlDiffNode.DiffNodeType.ToString(), FromValue = fromValue, ToValue = toValue, Parent = parent }; if (parent == null) { if (xmlDiffNode.DiffType == XmlDiffNode.DiffTypes.Added) { result.IsRootInsert = true; } } else { result.IsRootInsert = parent.IsRootInsert; } resultDtos.Add(result); if (xmlDiffNode.Descendants != null && xmlDiffNode.Descendants.Count > 0) { foreach (var descendant in xmlDiffNode.Descendants) { MakeResult(descendant, resultDtos, result); } } }
internal virtual void InsertChildNodeAfter(XmlDiffNode childNode, XmlDiffNode newChildNode) { newChildNode._parent = this; if (childNode == null) { newChildNode._nextSibling = this._firstChildNode; this._firstChildNode = newChildNode; } else { newChildNode._nextSibling = childNode._nextSibling; childNode._nextSibling = newChildNode; } this._nodesCount += newChildNode.NodesCount; if (newChildNode.NodeType == XmlDiffNodeType.Element || newChildNode is XmlDiffAttributeOrNamespace) { return; } this._elementChildrenOnly = false; }
// This function writes the result in XML format so that it can be used by other applications to display the diff private void WriteResult(XmlDiffNode sourceNode, XmlDiffNode targetNode, DiffType result) { if (DontWriteAnythingToOutput) { return; } if (result != DiffType.Success || !DontWriteMatchingNodesToOutput) { _Writer.WriteStartElement(string.Empty, "Node", string.Empty); _Writer.WriteAttributeString(string.Empty, "SourceLineNum", string.Empty, (sourceNode != null) ? sourceNode.LineNumber.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "SourceLinePos", string.Empty, (sourceNode != null) ? sourceNode.LinePosition.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "TargetLineNum", string.Empty, (targetNode != null) ? targetNode.LineNumber.ToString() : "-1"); _Writer.WriteAttributeString(string.Empty, "TargetLinePos", string.Empty, (targetNode != null) ? targetNode.LinePosition.ToString() : "-1"); } if (result == DiffType.Success) { if (!DontWriteMatchingNodesToOutput) { _Writer.WriteStartElement(string.Empty, "Diff", string.Empty); _Writer.WriteEndElement(); _Writer.WriteStartElement(string.Empty, "Lexical-equal", string.Empty); if (sourceNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(sourceNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteCData(GetNodeText(sourceNode, result)); } _Writer.WriteEndElement(); } } else { _Writer.WriteStartElement(string.Empty, "Diff", string.Empty); _Writer.WriteAttributeString(string.Empty, "DiffType", string.Empty, GetDiffType(result)); if (sourceNode != null) { _Writer.WriteStartElement(string.Empty, "File1", string.Empty); if (sourceNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(sourceNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteString(GetNodeText(sourceNode, result)); } _Writer.WriteEndElement(); } if (targetNode != null) { _Writer.WriteStartElement(string.Empty, "File2", string.Empty); if (targetNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(targetNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteString(GetNodeText(targetNode, result)); } _Writer.WriteEndElement(); } _Writer.WriteEndElement(); _Writer.WriteStartElement(string.Empty, "Lexical-equal", string.Empty); _Writer.WriteEndElement(); } if (result != DiffType.Success || !DontWriteMatchingNodesToOutput) { _Writer.WriteEndElement(); } }
// 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 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 = string.Empty; switch (diffNode.NodeType) { case XmlDiffNodeType.Element: if (result == DiffType.SourceExtra || result == DiffType.TargetExtra) return diffNode.OuterXml; StringWriter str = new StringWriter(); XmlWriter writer = XmlWriter.Create(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.Dispose(); break; case XmlDiffNodeType.CData: text = ((XmlDiffCharacterData)diffNode).Value; break; default: text = diffNode.OuterXml; break; } return text; }
// This function writes the result in XML format so that it can be used by other applications to display the diff private void WriteResult(XmlDiffNode sourceNode, XmlDiffNode targetNode, DiffType result) { _Writer.WriteStartElement(String.Empty, "Node", String.Empty); _Writer.WriteAttributeString(String.Empty, "SourceLineNum", String.Empty, (sourceNode != null) ? sourceNode.LineNumber.ToString() : "-1"); _Writer.WriteAttributeString(String.Empty, "SourceLinePos", String.Empty, (sourceNode != null) ? sourceNode.LinePosition.ToString() : "-1"); _Writer.WriteAttributeString(String.Empty, "TargetLineNum", String.Empty, (targetNode != null) ? targetNode.LineNumber.ToString() : "-1"); _Writer.WriteAttributeString(String.Empty, "TargetLinePos", String.Empty, (targetNode != null) ? targetNode.LinePosition.ToString() : "-1"); if (result == DiffType.Success) { _Writer.WriteStartElement(String.Empty, "Diff", String.Empty); _Writer.WriteEndElement(); _Writer.WriteStartElement(String.Empty, "Lexical-equal", String.Empty); if (sourceNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(sourceNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteCData(GetNodeText(sourceNode, result)); } _Writer.WriteEndElement(); } else { _Writer.WriteStartElement(String.Empty, "Diff", String.Empty); _Writer.WriteAttributeString(String.Empty, "DiffType", String.Empty, GetDiffType(result)); if (sourceNode != null) { _Writer.WriteStartElement(String.Empty, "File1", String.Empty); if (sourceNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(sourceNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteString(GetNodeText(sourceNode, result)); } _Writer.WriteEndElement(); } if (targetNode != null) { _Writer.WriteStartElement(String.Empty, "File2", String.Empty); if (targetNode.NodeType == XmlDiffNodeType.CData) { _Writer.WriteString("<![CDATA["); _Writer.WriteCData(GetNodeText(targetNode, result)); _Writer.WriteString("]]>"); } else { _Writer.WriteString(GetNodeText(targetNode, result)); } _Writer.WriteEndElement(); } _Writer.WriteEndElement(); _Writer.WriteStartElement(String.Empty, "Lexical-equal", String.Empty); _Writer.WriteEndElement(); } _Writer.WriteEndElement(); }
// 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 (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) { //Console.WriteLine( (sourceChild!=null)?(sourceChild.NodeType.ToString()):"null" ); //Console.WriteLine( (targetChild!=null)?(targetChild.NodeType.ToString()):"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); _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; _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; }