Esempio n. 1
0
        /// <summary>
        /// Gets the minimal set of edits needed to transform the specified expected text into the specified actual text.
        /// </summary>
        /// <param name="expectedText">The expected text.</param>
        /// <param name="actualText">The actual text.</param>
        /// <param name="excludeEmptyNodes">Should empty nodes be excluded from the results?</param>
        /// <param name="predicate">If true, the <see cref="XElement"/> will not be loaded.</param>
        /// <returns>The minimal set of edits needed to transform the specified expected text into the specified actual text.</returns>
        internal static IEnumerable <NodeEdit> GetEdits(string expectedText, string actualText, bool excludeEmptyNodes, Func <XElement, bool> predicate)
        {
            var schemaRegistry     = new SchemaRegistry();
            var expectedNodeInfo   = NodeInfo.Parse(expectedText, predicate, schemaRegistry);
            var actualNodeInfo     = NodeInfo.Parse(actualText, predicate, schemaRegistry);
            var expectedNodeGroups = Node.CreateGroups(expectedNodeInfo, schemaRegistry, out var expectedNodeCount);
            var actualNodeGroups   = Node.CreateGroups(actualNodeInfo, schemaRegistry, out var actualNodeCount);
            var nodeComparer       = new NodeComparer(expectedNodeCount, actualNodeCount);
            var edits = new List <NodeEdit>();

            foreach (var key in expectedNodeGroups.Keys.Union(actualNodeGroups.Keys))
            {
                if (expectedNodeGroups.TryGetValue(key, out var expectedNodes))
                {
                    edits.AddRange(actualNodeGroups.TryGetValue(key, out var actualNodes) ? GetEdits(expectedNodes, actualNodes, nodeComparer, excludeEmptyNodes) : expectedNodes.Where(node => !excludeEmptyNodes || !node.IsEmpty).Select(node => new NodeEdit(null, node, Operation.Removed)));
                }
                else if (actualNodeGroups.TryGetValue(key, out var actualNodes))
                {
                    edits.AddRange(actualNodes.Where(node => !excludeEmptyNodes || !node.IsEmpty).Select(node => new NodeEdit(node, null, Operation.Added)));
                }
            }

            return(edits);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the minimal set of edits needed to transform the specified expected nodes into the specified actual nodes.
        /// </summary>
        /// <param name="expectedNodes">The expected nodes.</param>
        /// <param name="actualNodes">The actual nodes.</param>
        /// <param name="nodeComparer">The comparer used to determine node similarity.</param>
        /// <param name="excludeEmptyNodes">Should empty nodes be excluded from the results?</param>
        /// <returns>A new <see cref="NodeEdit"/> for each <see cref="NodePair"/> where the nodes are not identical.</returns>
        private static IEnumerable <NodeEdit> GetEdits(ImmutableArray <Node> expectedNodes, ImmutableArray <Node> actualNodes, NodeComparer nodeComparer, bool excludeEmptyNodes)
        {
            const float epsilon = 0.00001f;

            var count   = 0;
            var maximum = Math.Min(expectedNodes.Length, actualNodes.Length);

            foreach (var nodePair in nodeComparer.GetNodePairs(expectedNodes, actualNodes).OrderByDescending(nodePair => nodePair.AverageScore))
            {
                if (!nodePair.TryCreateMatch())
                {
                    continue;
                }

                if (Math.Abs(nodePair.NodeScore - 1.0f) > epsilon)
                {
                    yield return(new NodeEdit(nodePair.ActualNode, nodePair.ExpectedNode, Operation.Modified));
                }

                if (maximum == ++count)
                {
                    break;
                }
            }

            foreach (var expectedNode in expectedNodes.Where(expectedNode => !expectedNode.IsMatched && (!excludeEmptyNodes || !expectedNode.IsEmpty)))
            {
                yield return(new NodeEdit(null, expectedNode, Operation.Removed));
            }

            foreach (var actualNode in actualNodes.Where(actualNode => !actualNode.IsMatched && (!excludeEmptyNodes || !actualNode.IsEmpty)))
            {
                yield return(new NodeEdit(actualNode, null, Operation.Added));
            }
        }