Example #1
0
        private void GetKeyPositions(IEnumerable <XmlNode> input, Action <XmlNode, KeyPosition> saveIt)
        {
            Dictionary <string, int> Occurrences = new Dictionary <string, int>();

            foreach (XmlNode node in input)
            {
                if (node.Attributes == null)
                {
                    continue;
                }
                if (node.Name != _elementName)
                {
                    continue;
                }
                var key1 = XmlUtilities.GetOptionalAttributeString(node, _keyAttribute);
                if (string.IsNullOrEmpty(key1))
                {
                    continue;
                }
                int oldCount;
                Occurrences.TryGetValue(key1, out oldCount);
                saveIt(node, new KeyPosition(key1, oldCount));
                Occurrences[key1] = oldCount + 1;
            }
        }
Example #2
0
        public XmlNode GetNodeToMerge(XmlNode nodeToMatch, XmlNode parentToSearchIn, HashSet <XmlNode> acceptableTargets)
        {
            if (parentToSearchIn == null || nodeToMatch == null)
            {
                return(null);
            }
            var keyVal = nodeToMatch.Attributes[_key];

            if (keyVal != null)
            {
                foreach (XmlNode node in parentToSearchIn.ChildNodes)
                {
                    if (!acceptableTargets.Contains(node) || !(node is XmlElement))
                    {
                        continue;
                    }
                    if (XmlUtilities.GetOptionalAttributeString(node, _key) == keyVal.Value)
                    {
                        return(node);
                    }
                }
            }

            return(_backup.GetNodeToMerge(nodeToMatch, parentToSearchIn, acceptableTargets));
        }
Example #3
0
        public XmlNode GetNodeToMerge(XmlNode nodeToMatch, XmlNode parentToSearchIn, HashSet <XmlNode> acceptableTargets)
        {
            if (parentToSearchIn == null)
            {
                return(null);
            }

            var key = XmlUtilities.GetOptionalAttributeString(nodeToMatch, _keyAttribute);

            if (string.IsNullOrEmpty(key))
            {
                return(null);
            }

#if USEOPTIMIZEDVERSION
            var parentIdx = _parentsToSearchIn.IndexOf(parentToSearchIn);
            if (parentIdx == -1)
            {
                _parentsToSearchIn.Add(parentToSearchIn);
                parentIdx = _parentsToSearchIn.IndexOf(parentToSearchIn);
                var childrenWithKeys = new Dictionary <string, XmlNode>();                // StringComparer.OrdinalIgnoreCase NO: Bad idea, since I (RBR) saw a case in a data file that had both upper and lower-cased variations.
                _indexedSoughtAfterNodes.Add(parentIdx, childrenWithKeys);
                var matchingName        = nodeToMatch.Name;
                var childrenWithKeyAttr = (from XmlNode childNode in parentToSearchIn.ChildNodes
                                           where childNode.Name == matchingName && childNode.Attributes[_keyAttribute] != null
                                           select childNode).ToList();
                foreach (var nodeWithKeyAttribute in childrenWithKeyAttr)
                {
                    childrenWithKeys.Add(nodeWithKeyAttribute.Attributes[_keyAttribute].Value, nodeWithKeyAttribute);
                }
            }

            XmlNode matchingNode;
            _indexedSoughtAfterNodes[parentIdx].TryGetValue(key, out matchingNode);
            // JohnT: consider replacing the line above with this if we decide to deal with duplicate keys. This branch currently won't cope with this,
            // because the Add above will fail on any duplicate key.
            //if (_indexedSoughtAfterNodes[parentIdx].TryGetValue(key, out matchingNode) && !acceptableTargets.Contains(matchingNode))
            //{
            //    // The one we retrieved is not acceptable (typically we concluded it should be deleted).
            //    // It's just possible that there's a duplicate key, and one of the acceptable matches is also a match.
            //    // Not finding a match is relatively rare, so try a sequential search.
            //    // We don't just search in acceptableTargets itself, because we still prefer the first (acceptable) match.
            //    return (from XmlNode node in parentToSearchIn.ChildNodes
            //        where node is XmlElement && acceptableTargets.Contains(node) && GetKey(node) == key
            //        select node).FirstOrDefault();
            //}
            return(matchingNode);            // May be null, which is fine.
#else
            var matches = GetMatchingNodes(nodeToMatch, parentToSearchIn).Where(node => acceptableNodes.Contains(node).toList();
                                                                                return((matches.Count > 0) ? matches[0] : null);
#endif
        }
Example #4
0
        public XmlNode GetNodeToMerge(XmlNode nodeToMatch, XmlNode parentToSearchIn, HashSet <XmlNode> acceptableTargets)
        {
            if (parentToSearchIn == null)
            {
                return(null);
            }

            string key = XmlUtilities.GetOptionalAttributeString(nodeToMatch, _keyAttribute);

            if (string.IsNullOrEmpty(key))
            {
                return(null);
            }

            if (nodeToMatch.ParentNode == null)
            {
                return(null);
            }

            if (nodeToMatch.Name != _elementName)
            {
                _parentNode  = _sourceNode = null;                // force regenerate both maps
                _elementName = nodeToMatch.Name;
            }

            if (_sourceNode != nodeToMatch.ParentNode)
            {
                _sourceMap.Clear();
                _sourceNode = nodeToMatch.ParentNode;
                GetKeyPositions(_sourceNode.ChildNodes.Cast <XmlNode>(), (node, kp) => _sourceMap[node] = kp);
            }

            if (_parentNode != parentToSearchIn || acceptableTargets != null)
            {
                _parentMap.Clear();
                _parentNode = parentToSearchIn;
                GetKeyPositions(_parentNode.ChildNodes.Cast <XmlNode>().Where(node => acceptableTargets.Contains(node)),
                                (node, kp) => _parentMap[kp] = node);
            }

            KeyPosition targetKp;

            if (!_sourceMap.TryGetValue(nodeToMatch, out targetKp))
            {
                return(null);
            }
            XmlNode result;

            _parentMap.TryGetValue(targetKp, out result);
            return(result);
        }
Example #5
0
        /// <summary>
        /// Get all matching nodes, or an empty collection, if there are no matches.
        /// </summary>
        /// <returns>A collection of zero, or more, matching nodes.</returns>
        /// <remarks><paramref name="nodeToMatch" /> may, or may not, be a child of <paramref name="parentToSearchIn"/>.</remarks>
        public IEnumerable <XmlNode> GetMatchingNodes(XmlNode nodeToMatch, XmlNode parentToSearchIn)
        {
            if (parentToSearchIn == null)
            {
                return(new List <XmlNode>());
            }

            var key = XmlUtilities.GetOptionalAttributeString(nodeToMatch, _keyAttribute);

            if (string.IsNullOrEmpty(key))
            {
                return(new List <XmlNode>());
            }

            var matches = new List <XmlNode>();

            foreach (XmlNode childNode in parentToSearchIn.ChildNodes)
            {
                if (childNode.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                if (nodeToMatch == childNode)
                {
                    matches.Add(childNode);
                    continue;
                }
                var keyAttr = childNode.Attributes[_keyAttribute];
                if (keyAttr == null || keyAttr.Value != key)
                {
                    continue;
                }
                matches.Add(childNode);
            }
            return(matches);
        }