From 4553a263934c6367dfbebf38308c7fb50f9ea9e4 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Thu, 16 Dec 2021 18:29:36 +0100 Subject: [PATCH] port xmlunit/#236 --- RELEASE_NOTES.md | 4 +++ src/main/net-core/Diff/DOMDifferenceEngine.cs | 36 +++++++++++++------ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 97b5fe6..7d04737 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,10 @@ ## XMLUnit.NET 2.9.1 - /not released, yet/ +* improved comparison performance for documents with many siblings + based on a suggestion by [@gerpres](https://github.com/gerpres) made + in Java Issue [xmlunit/#236](https://github.com/xmlunit/xmlunit/issues/236) + * added a new `FullDescription` method to `Diff` that provides a string-representation of all differences - not just the first one like `ToString` does. diff --git a/src/main/net-core/Diff/DOMDifferenceEngine.cs b/src/main/net-core/Diff/DOMDifferenceEngine.cs index 8fc3fd0..6a1d90a 100644 --- a/src/main/net-core/Diff/DOMDifferenceEngine.cs +++ b/src/main/net-core/Diff/DOMDifferenceEngine.cs @@ -472,16 +472,22 @@ private ComparisonState CompareNodeLists(IEnumerable allControlChildren IList testListForXpath = new List(allTestChildren); IList controlList = new List(controlSeq); IList testList = new List(testSeq); + + IDictionary controlListForXpathIndex = Index(controlListForXpath); + IDictionary testListForXpathIndex = Index(testListForXpath); + IDictionary controlListIndex = Index(controlList); + IDictionary testListIndex = Index(testList); + ICollection seen = new HashSet(); foreach (KeyValuePair pair in matches) { XmlNode control = pair.Key; seen.Add(control); XmlNode test = pair.Value; seen.Add(test); - int controlIndexForXpath = controlListForXpath.IndexOf(control); - int testIndexForXpath = testListForXpath.IndexOf(test); - int controlIndex = controlList.IndexOf(control); - int testIndex = testList.IndexOf(test); + int controlIndexForXpath = controlListForXpathIndex[control]; + int testIndexForXpath = testListForXpathIndex[test]; + int controlIndex = controlListIndex[control]; + int testIndex = testListIndex[test]; controlContext.NavigateToChild(controlIndexForXpath); testContext.NavigateToChild(testIndexForXpath); try { @@ -500,13 +506,13 @@ private ComparisonState CompareNodeLists(IEnumerable allControlChildren } return chain - .AndThen(UnmatchedControlNodes(controlListForXpath, controlList, controlContext, + .AndThen(UnmatchedControlNodes(controlListForXpathIndex, controlList, controlContext, seen, testContext)) - .AndThen(UnmatchedTestNodes(testListForXpath, testList, testContext, seen, - controlContext)); + .AndThen(UnmatchedTestNodes(testListForXpathIndex, testList, testContext, + seen, controlContext)); } - private Func UnmatchedControlNodes(IList controlListForXpath, + private Func UnmatchedControlNodes(IDictionary controlListForXpathIndex, IList controlList, XPathContext controlContext, ICollection seen, @@ -517,7 +523,7 @@ private Func UnmatchedControlNodes(IList controlListFo for (int i = 0; i < controlSize; i++) { if (!seen.Contains(controlList[i])) { controlContext - .NavigateToChild(controlListForXpath.IndexOf(controlList[i])); + .NavigateToChild(controlListForXpathIndex[controlList[i]]); try { chain = chain .AndThen(new Comparison(ComparisonType.CHILD_LOOKUP, @@ -536,7 +542,7 @@ private Func UnmatchedControlNodes(IList controlListFo }; } - private Func UnmatchedTestNodes(IList testListForXpath, + private Func UnmatchedTestNodes(IDictionary testListForXpathIndex, IList testList, XPathContext testContext, ICollection seen, @@ -546,7 +552,7 @@ private Func UnmatchedTestNodes(IList testListForXpath int testSize = testList.Count; for (int i = 0; i < testSize; i++) { if (!seen.Contains(testList[i])) { - testContext.NavigateToChild(testListForXpath.IndexOf(testList[i])); + testContext.NavigateToChild(testListForXpathIndex[testList[i]]); try { chain = chain .AndThen(new Comparison(ComparisonType.CHILD_LOOKUP, @@ -737,5 +743,13 @@ private static XmlAttribute FindMatchingAttr(IList attrs, return null; } + private static IDictionary Index(IList nodes) { + IDictionary indices = new Dictionary(); + int idx = 0; + foreach (XmlNode n in nodes) { + indices[n] = idx++; + } + return indices; + } } }