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; } }
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)); }
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 }
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); }
/// <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); }