/// <summary> /// Returns new SDF hierarchy where all elements matching to given SDF Path are replaced with a copy of given SDF. /// If root element matches the given path, given SDF is returned (not a copy of it). /// </summary> /// <param name="path">SDF Path for elements to match to.</param> /// <param name="newValue">SDF to replaced matching elements with.</param> /// <returns>Reference to either updated <c>this</c> or <c>newValue</c>.</returns> public SDF Replace(string path, SDF newValue) { var topMatches = FindTopMatches(path); foreach (var m in topMatches) { if (m.Parent == null) { // if root is being replaced return(newValue); } var oldValue = m.Value; var parent = m.Parent.Value as Node; // parents can only be nodes if (parent == null) { throw new InvalidDataException("Element has parent which is not a Node (impossible)."); } var index = parent.Children.IndexOf(oldValue); if (index != -1) { parent.Children[index] = newValue.DeepCopy(); } else // not a child, then must be an attribute { var found = false; foreach (var pair in parent.Attributes) { if (pair.Value == oldValue) { parent.Attributes[pair.Key] = newValue.DeepCopy(); found = true; break; } } if (!found) { throw new InvalidDataException("Cannot replace element because element's parent doesn't have it neither as a child nor as an attribute."); } } } return(this); }
/// <summary> /// Inserts a clone of <c>value</c> as a child to all elements matching given SDF Path at position <c>index</c>. /// </summary> /// <param name="path">SDF Path for elements to match to.</param> /// <param name="index">Position to insert into.</param> /// <param name="value">Value to be inserted.</param> public void InsertAt(string path, int index, SDF value) { var matches = Find(path); foreach (var match in matches) { var node = match.Value as Node; if (node == null) { throw new InvalidDataException("Cannot insert a child into something but a Node."); } node.Children.Insert(index, value.DeepCopy()); } }
/// <summary> /// Adds a clone of <c>value</c> as a child to all elements matching given SDF Path. /// Can only apply to nodes. /// </summary> /// <param name="path">SDF Path for elements to match to.</param> /// <param name="value">Value of the added child.</param> public void AddChild(string path, SDF value) { var matches = Find(path); foreach (var match in matches) { var node = match.Value as Node; if (node == null) { throw new InvalidDataException("Cannot add a child to something but a Node."); } node.Children.Add(value.DeepCopy()); } }
/// <summary> /// Adds an attribute with <c>attributeName</c> name and <c>value</c> value to all elements matching given SDF Path. /// Can only apply to nodes. /// Throws an exception if attribute with given name already exists on a matching element. /// </summary> /// <param name="path">SDF Path for elements to match to.</param> /// <param name="attributeName">Name of the added attribute.</param> /// <param name="value">Value of the added attribute.</param> public void AddAttribute(string path, string attributeName, SDF value) { var matches = Find(path); foreach (var match in matches) { var node = match.Value as Node; if (node == null) { throw new InvalidDataException("Cannot add an attribute to something but a Node."); } if (node.Attributes.ContainsKey(attributeName)) { throw new InvalidDataException("Cannot add an attribute, because attribute with such name already exists."); } node.Attributes[attributeName] = value.DeepCopy(); } }
/// <summary> /// Inserts a clone of <c>value</c> after all elements matching given SDF Path. /// Throws an exception if adding next to root element. /// </summary> /// <param name="path">SDF Path for elements to match to.</param> /// <param name="value">Value to be inserted.</param> public void InsertAfter(string path, SDF value) { var matches = Find(path); foreach (var match in matches) { if (match.Parent == null) { throw new InvalidDataException("Cannot add something next to root element."); } var node = match.Parent.Value as Node; if (node == null) { throw new InvalidDataException("Cannot insert a child into something but a Node."); } node.InsertAfterChild(match.Value, value.DeepCopy()); } }