private void FillIn(Expression xpath, XmlNode topContext) { //initialize the context node XmlNode current = topContext; //start looking down the document tree for (int length = 1; length <= xpath.StepCount; ++length) { Expression sub = xpath.SubExpression(length); //check to see if the node already exists... XmlNodeList nodes = topContext.SelectNodes(sub.ToString(true), this._namespaces); if (nodes.Count == 0) { //... and create it if it doesn't LocationStep step = sub.LastStep; if (step.IsAttribute) { XmlAttribute attribute = this._document.CreateAttribute(step.NodeTest.Test); current.Attributes.Append(attribute); current = attribute; } else { string namespaceUri = this._namespaces.LookupNamespace(step.NodeTest.Namespace); XmlNode element = this._document.CreateElement(step.NodeTest.Namespace, step.NodeTest.Test, namespaceUri); current.AppendChild(element); current = element; } //if there were attribute filters applied to the xpath, then apply them here if (step.Predicates.Count > 0) { foreach (Predicate predicate in step.Predicates) { if (predicate.IsAttributeFilter) { XmlAttribute attribute = this._document.CreateAttribute(predicate.FilterKey.Substring(1)); attribute.Value = predicate.FilterValue; current.Attributes.Append(attribute); } } } } else if (nodes.Count == 1) //...otherwise, advance the context { current = nodes[0]; } else //in the case of multiples, do it to all of them { foreach (XmlNode child in nodes) { FillIn(xpath.SubExpression(length, xpath.StepCount - length), child); } } } }
/// <summary> /// Adds a location step to the end of the xpath, if the current xpath does not reference an Attribute /// </summary> /// <param name="locationStep"></param> public void AddStep(LocationStep locationStep) { if (!this.IsAttribute) { this._components.Add(locationStep); } if (this._standardPrefix != null) { locationStep.NodeTest.Namespace = this._standardPrefix; } }
/// <summary> /// Compares two location steps for equality. They must represent the same Axis Specifier, same Node Test /// and equivalent sets of Predicates. /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { if (obj is LocationStep) { LocationStep step = (LocationStep)obj; return(this.ToString(true).Equals(step.ToString(true))); } else { return(false); } }
public LocationStep GetLocationStepByNodeTest(string p) { LocationStep locationStep = null; foreach (LocationStep step in this._components) { if (step.NodeTest.Test.Equals(p)) { locationStep = step; } } return(locationStep); }
/// <summary> /// Tokenizes a provided XPath expression /// </summary> /// <param name="exp"></param> public Expression(string exp) : this() { try { exp = exp.Replace("//", "/descendant::"); if (exp[0] == '/') { this._isFromRoot = true; exp = exp.Substring(1); } else { this._isFromRoot = false; } string[] parts = exp.Split('/'); string namespacePrefix = null; bool allHavePrefix = true; foreach (string part in parts) { LocationStep step = new LocationStep(part); this._components.Add(step); if (step.NodeTest.Namespace == null || (namespacePrefix != null && !step.NodeTest.Namespace.Equals(namespacePrefix))) { allHavePrefix = false; } else { namespacePrefix = step.NodeTest.Namespace; } } if (allHavePrefix) { this._standardPrefix = namespacePrefix; } } catch (Exception exception) { throw new Exception(string.Format("Could not construct XPath expression from input string(\"{0}\")", exp), exception); } }