public void Enumerable_Create1_SiblingAdd() { XElement root = new XElement("root", new XElement("NodeA", new XElement("Id", "a"))); XElement notexpected = new XElement("root"); XPathString xpath = new XPathString("//NodeA[Id={0}]/ChildA[@key={1}]", "A", "1"); var actual = cXPath.Enumerable(root, xpath, true); Assert.AreNotEqual(root.ToString(), notexpected.ToString()); // root was changed }
public void Enumerable_CreateNode_RootUnchanged() { XElement root = new XElement("root"); XElement expected = new XElement("root"); XPathString xpath = new XPathString("//NodeA[Id={0}]/ChildA[@key={1}]", "A", "1"); var actual = cXPath.Enumerable(root, xpath, true); Assert.AreEqual(root.ToString(), expected.ToString()); // root remains unchanged }
public void Enumerable_CreateNode_RootUnchanged1() { XElement root = new XElement("root"); XElement expected = new XElement("ChildA", new XAttribute("key", "1")); XPathString xpath = new XPathString("//NodeA[Id={0}]/ChildA[@key={1}]", "A", "1"); XElement actual = cXPath.Enumerable(root, xpath, true).First(); Assert.AreEqual(actual.ToString(), expected.ToString()); }
public void IsXPath_PathWithBrackets() { string path = "part[key=value]"; object[] values = null; XPathString target = new XPathString(path, values); bool actual, expected = true; actual = target.IsXPath; Assert.AreEqual(expected, actual); }
public void IsXPath_JustAPath() { string path = "part/path/nodes"; object[] values = new object[] { }; XPathString target = new XPathString(path, values); bool actual, expected = false; actual = target.IsXPath; Assert.AreEqual(expected, actual); }
public void Elements_currentNodeEqualsValue() { XPathString path = new XPathString("[.='Mike']"); XPath_Bracket target = new XPath_Bracket(path); IEnumerable<XElement> elements = root.Descendants(); var expected = root.Descendants() .Where(xe => xe.Value == "Mike").ToArray(); var actual = target.Elements(elements).ToArray(); CollectionAssert.AreEqual(expected, actual); }
public void Combine() { string path = "pair[path/to/@Key={0}]/Items/Item[Name={1}]/Date"; object[] values = new object[] { 2, "Martin" }; XPathString xp = new XPathString(path, values); string expected = "pair[path/to/@Key={0}]/Items/Item[Name={1}]"; XPathString actual = XPathString.Combine(xp.PathSegments.Take(3)); Assert.AreEqual(expected, actual.Format); CollectionAssert.AreEqual(values, actual.Values); }
public XPath_Bracket(XPathString path) { string text = path.Format; XPath = path.Text.TrimStart('[').TrimEnd(']'); text = text.TrimStart('[').TrimEnd(']'); AndOr = text.Contains(" and "); // need new XPathString() that has brackets removed. XPathString[] paths = new XPathString(true, text, path.Values) .Split(new string[] { " and ", " or " }, StringSplitOptions.RemoveEmptyEntries, true); Parts = paths.Select(s => new XPath_Part(s)).ToArray(); }
public void Enumerable_Create1_SiblingAdd2() { // Add not-found NodeA as a sibling to another NodeA XElement root = new XElement("root", new XElement("NodeA", new XElement("Id", "a"))); XElement expected = new XElement("root", new XElement("NodeA", new XElement("Id", "a"))); expected.Add(new XElement("NodeA", new XElement("Id", "A"), new XElement("ChildA", new XAttribute("key", "1")) )); XPathString xpath = new XPathString("//NodeA[Id={0}]/ChildA[@key={1}]", "A", "1"); var actual = cXPath.Enumerable(root, xpath, true); Assert.AreEqual(root.ToString(), expected.ToString()); // root was changed }
public void Enumerable_Create1_ChildAdd1() { // Add not-found key element to existing NodeA element XElement root = new XElement("root", new XElement("NodeA", new XElement("Id", "A"))); XElement expected = new XElement("root", new XElement("NodeA", new XElement("Id", "A"), new XElement("ChildA", new XAttribute("key", "1")) ) ); XPathString xpath = new XPathString("//NodeA[Id={0}]/ChildA[@key={1}]", "A", "1"); var actual = cXPath.Enumerable(root, xpath, true); Assert.AreEqual(root.ToString(), expected.ToString()); // root was changed }
public void XPath_Bracket_Constructor() { XPathString path = new XPathString("[.='Mike']"); XPath_Bracket target = new XPath_Bracket(path); Assert.AreEqual(target.Parts.Length, 1); var part = target.Parts[0]; Assert.AreEqual(part.ElementAt, false); Assert.AreEqual(part.Equal, true); Assert.AreEqual(part.Function, null); Assert.AreEqual(part.GreaterThan, false); Assert.AreEqual(part.GreaterThanOrEqual, false); Assert.AreEqual(part.IsValueAttribute, false); Assert.AreEqual(part.Key, "."); Assert.AreEqual(part.KVP, true); Assert.AreEqual(part.LessThan, false); Assert.AreEqual(part.LessThanOrEqual, false); Assert.AreEqual(part.NotEqual, false); Assert.AreEqual(part.Value, "Mike"); }
public void XPath_Part_KVP_GTEqualR() { XPathString path = new XPathString("[{0}>=to]", 0); XPath_Bracket target = new XPath_Bracket(path); Assert.AreEqual(target.Parts.Length, 1); var part = target.Parts[0]; // XPath_Part becomes "to < {0}" Assert.AreEqual(part.ElementAt, false); Assert.AreEqual(part.IsValueAttribute, false); Assert.AreEqual(part.KVP, true); Assert.AreEqual(null, part.Function); Assert.AreEqual(part.Equal, false); Assert.AreEqual(part.GreaterThan, false); Assert.AreEqual(part.GreaterThanOrEqual, false); Assert.AreEqual(part.LessThan, true); Assert.AreEqual(part.LessThanOrEqual, false); Assert.AreEqual(part.NotEqual, false); Assert.AreEqual(part.Key, "to"); Assert.AreEqual(part.Value, 0); }
public void IsXPath_PathWithoutBrackets() { string path = "//part"; object[] values = null; XPathString target = new XPathString(path, values); bool actual, expected = false; actual = target.IsXPath; Assert.AreEqual(expected, actual); }
public void XPath_Part_KVP_Right() { /* * Swaps the expression to be [@to >= {0}] * So we compare for > and >= */ XPathString path = new XPathString("[{0} < @to]", 0); XPath_Bracket target = new XPath_Bracket(path); Assert.AreEqual(target.Parts.Length, 1); var part = target.Parts[0]; // XPath_Part Assert.AreEqual(part.ElementAt, false); Assert.AreEqual(null, part.Function); Assert.AreEqual(part.IsValueAttribute, true); Assert.AreEqual(part.KVP, true); Assert.AreEqual(part.Equal, true); Assert.AreEqual(part.GreaterThan, true); Assert.AreEqual(part.GreaterThanOrEqual, true); Assert.AreEqual(part.LessThan, false); Assert.AreEqual(part.LessThanOrEqual, false); Assert.AreEqual(part.NotEqual, false); Assert.AreEqual(part.Key, "to"); Assert.AreEqual(part.Value, 0); }
public void Split_overrideEquals() { string path = "pair[path/to/@Key={0}]/Items/Item[Name={1}]/Date"; object[] values = new object[] { 2, "Martin" }; XPathString target = new XPathString(path, values); XPathString[] expected = new[]{ new XPathString("pair[path/to/@Key={0}]", 2), new XPathString("Items"), new XPathString("Item[Name={0}]", "Martin"), new XPathString("Date") }; XPathString[] actual; actual = target.Split(); CollectionAssert.AreEqual(expected, actual); }
public void XPathElementTest() { XPathString path = new XPathString("pair[@Key={0}]/Items/Item[Name={1}]", 2, "Martin"); bool create = false; XElement expected = root.Elements("pair") .Where(x => ((int)x.Attribute("Key")) == 2) .SelectMany(x => x.Element("Items").Elements("Item")) .Where(x => ((string)x.Element("Name")) == "Martin") .FirstOrDefault(); XElement actual; actual = XPathExtensions.XPathElement(root, path, create); Assert.AreEqual(expected, actual); }
public void XPathStringConstructor_EmptyPath() { string path = string.Empty; object[] values = null; XPathString target = new XPathString(path, values); }
public void ToPaths_Same() { string path = "same"; object[] values = null; XPathString target = new XPathString(path, values); XPathString[] expected = new[] { target }; XPathString[] actual = target.ToPaths(true, path); CollectionAssert.AreEqual(expected, actual); }
public void XPathStringConstructor_Path_EmbeddedValues() { string path = "pair[@Key=2]/Items/Item[Name='Martin']/Date"; object[] values = null; XPathString target = new XPathString(path, values); string actual, expected = "pair[@Key=2]/Items/Item[Name='Martin']/Date"; actual = target.Text; Assert.AreEqual(expected, actual); }
public void XPathStringConstructor_NullPath() { string path = null; object[] values = null; XPathString target = new XPathString(path, values); }
/// <summary> /// Get the elements of a path "path/to/node" or "path[to/node/@attribute>=20.50]". /// <remarks> /// <para>See XPath docs for help on using [number][key=value] /// - syntax (http://www.w3.org/TR/xpath/)</para> /// </remarks> /// </summary> /// <param name="source"></param> /// <param name="path"></param> /// <param name="create">create path if it doesn't exist?</param> /// <exception cref="ArgumentOutOfRangeException" /> public static IEnumerable<XElement> Enumerable(XElement source, XPathString path, bool create) { IEnumerable<XElement> enumerableXElement; if (null == path) throw new ArgumentNullException("Path cannot be null."); if (!path.IsRelative) source = source.Root(); List<XElement> list = new[] { source }.ToList(); for (int i = 0; i < path.PathSegments.Length; i++) { List<XElement> newList = new List<XElement>(); XPathString xpathString = path.PathSegments[i]; //bool last = (i + 1) == path.PathSegments.Length; if (xpathString.IsXPath) { bool foundOne = false; list.ForEach(xElement => { enumerableXElement = ParseInternal(xElement, xpathString); if (null != enumerableXElement) { newList.AddRange(enumerableXElement.ToList()); foundOne = true; } }); if (foundOne) { list = newList; continue; } } list.ForEach(xElement => newList.AddRange(PartToElements(xElement, xpathString))); list = newList; } // If the node wasn't found and we were asked to create it, do the best we can // If it is a simple search, then we won't be able to place the node and it will be dangling (without a parent node) if (list.Count == 0 && create) { // Find parent element if we can, and plug in the new node there XElement parent = null; foreach (var seg in path.PathSegments.Take(path.PathSegments.Length - 1)) parent = (parent ?? source).XPathElement(seg, create); // If not found, try finding a sibling without search parameters // and use it's parent. if (null == parent) { XPathString clean = path.Clone_NoBrackets(); XElement sibling = source.XPathElement(clean, false); if (null != sibling) parent = sibling.Parent; } // Using last segment in XPath, create the node that is missing var segment = path.PathSegments.Last(); XElement node = new XElement(segment.Name); if (null != parent) parent.Add(node); // Add any child element's or attribute's that were requested in the search foreach (var b in segment.Brackets) { foreach (var part in b.Parts) { if (!part.Equal) continue; if (part.IsValueAttribute) node.Add(new XAttribute(part.Key, part.Value)); else node.Add(new XElement(part.Key, part.Value)); } } list.Add(node); } return list; }
public void SplitInternalTest() { string path = "pair[path/to/@Key={0}]/Items/Item[Name={1}]/Date"; object[] values = new object[] { 2, "Martin" }; XPathString xp = new XPathString(path, values); PrivateObject param0 = new PrivateObject(xp); XPathString_Accessor target = new XPathString_Accessor(param0); string[] expected = new string[] { "pair[path/to/@Key={0}]", "Items", "Item[Name={1}]", "Date" }; string[] actual; actual = target.SplitInternal(); CollectionAssert.AreEqual(expected, actual); }
public void XPathStringConstructor_Path_ExternalValues() { string path = "pair[@Key={0}]/Items/Item[Name={1}]/Date"; object[] values = new object[] { 2, "Martin" }; XPathString target = new XPathString(path, values); string actual, expected = "pair[@Key=2]/Items/Item[Name=Martin]/Date"; actual = target.Text; Assert.AreEqual(expected, actual); }
public XPath_Part(XPathString text) { self = text; string format = text.Format; if (Equal = format.Contains('=')) { SetKVP(format, '='); if (NotEqual = Key.EndsWith("!")) Key = Key.TrimEnd('!'); else if (LessThan = Key.EndsWith("<")) Key = Key.TrimEnd('<'); else if (GreaterThan = Key.EndsWith(">")) Key = Key.TrimEnd('>'); if (!LessThan && !GreaterThan) SwapSymbol = false; // don't swap Equal to false or NotEqual to true } else if (LessThan = format.Contains("<")) { SetKVP(format, '<'); } else if (GreaterThan = format.Contains(">")) { SetKVP(format, '>'); } if (SwapSymbol) { LessThan = !LessThan; GreaterThan = !GreaterThan; Equal = !Equal; } if (!string.IsNullOrEmpty(Key)) Key = Key.Trim(); { Match functionMatch = Regex.Match(format, @"^\w+[^\(]*\([^\)]*\)"); // last(), starts-with(key, value) if (functionMatch.Success) { string func = functionMatch.Value; string function = func.Split('(')[0].ToLower(); switch (function) { case "contains": Function = new Contains(this); break; case "ends-with": Function = new EndsWith(this); break; case "last": ElementAt = true; Key = functionMatch.Value; Match digits = Regex.Match(format, @"\d+$"); // ddd int i; if (digits.Success && int.TryParse(digits.Value, out i)) _Value = i; else _Value = 0; break; case "local-name": Function = new LocalName(this); break; case "max": case "min": Function = new MinMax(this, func); break; case "name": Function = new Name(this); break; case "string-length": Function = new StringLength(this); break; case "starts-with": Function = new StartsWith(this); break; case "substring": Function = new Substring(this); break; } if (null != Function) { string kvp = Regex.Match(func, @"\(([^\)]*)\)").Groups[1].Value;//.TrimStart('(').TrimEnd(')'); if (!string.IsNullOrEmpty(kvp)) Function.Args = kvp.Split(',').Select(s => Format(s)).ToArray(); if (Function.HasKVP) { if (!string.IsNullOrEmpty(kvp) || Function.ArgumentsRequired) { string[] parts = kvp.Split(','); try { if (null != Function.NodeSet) { Key = Function.NodeSet; Value = parts[1 - Function.NodeSet.Index]; } else { Key = parts[0]; Value = parts[1]; } } catch (IndexOutOfRangeException) { if (Function.ArgumentsValueRequired) throw new ArgumentException(string.Format( "Syntax {0}(key, value): Invalid {0}({1})", func.Split('(')[0], kvp)); } } else Key = string.Empty; } else if (Function.Args.Length > 0) Key = Function.Args[0].ToString(); else Key = string.Empty; if (Function.IsEqual) Equal = true; } } } if (null == Key) { // is this a [0] or [{0}] format? int i; object value = Format(format); if (ElementAt = value is int) { Value = (int)value; return; } if (ElementAt = int.TryParse(format, out i)) { Value = i; return; } Key = value.ToString(); } if (IsValueAttribute = Key.StartsWith("@")) Key = Key.Substring(1); if (Value is string && !valueIsString) { decimal d; if (decimal.TryParse((string)Value, out d)) _Value = d; } }
public void XPathString_Clone_NoBrackets() { XPathString xpath = new XPathString("//Site[Id={0}]/add[@key={1}]", "C", "landingName2"); XPathString actual = xpath.Clone_NoBrackets(); XPathString expected = new XPathString("//Site/add"); Assert.AreEqual(actual.Text, expected.Text); Assert.AreEqual(actual.IsRelative, expected.IsRelative); Assert.AreEqual(actual.IsElements, expected.IsElements); }
public void XPath_Bracket_Constructor2() { XPathString path = new XPathString("[min(Value2/Value, {0})]", 0); XPath_Bracket target = new XPath_Bracket(path); Assert.AreEqual(target.Parts.Length, 1); var part = target.Parts[0]; Assert.AreEqual(part.ElementAt, false); Assert.AreEqual(part.Equal, true); Assert.AreNotEqual(null, part.Function); Assert.IsInstanceOfType(part.Function, typeof(MinMax)); Assert.AreEqual(part.GreaterThan, false); Assert.AreEqual(part.GreaterThanOrEqual, false); Assert.AreEqual(part.IsValueAttribute, false); Assert.AreEqual(part.Key, "Value2/Value"); Assert.AreEqual(part.KVP, false); Assert.AreEqual(part.LessThan, false); Assert.AreEqual(part.LessThanOrEqual, false); Assert.AreEqual(part.NotEqual, false); Assert.AreEqual(part.Value, 0); }
private static IEnumerable<XElement> ParseInternal(XElement contextNode, XPathString part) { IEnumerable<XElement> elements = PartToElements(contextNode, part); foreach (XPath_Bracket bracket in part.Brackets) elements = bracket.Elements(elements); return elements; }
private static IEnumerable<XElement> PartToElements(XElement contextNode, XPathString xp) { string name = xp.Name; bool star = false; if (star = name.Contains('*')) { string[] parts = name.Split('*'); if (parts.Length > 2) throw new ArgumentException("Invalid name: " + name); name = parts[0]; } IEnumerable<XElement> elements; if (xp.IsElements) { if (string.IsNullOrEmpty(name) || star) elements = contextNode.Elements(); else elements = contextNode.GetElements(name); } else { if (string.IsNullOrEmpty(name) || star) elements = contextNode.Descendants(); else elements = contextNode.GetDescendants(name); } if (star && !string.IsNullOrEmpty(name)) elements = elements.Where(x => x.Name.LocalName.StartsWith(name)); return elements; }
public string XPathString_ConvertTo(string value) { return(XPathString.ConvertTo(value)); }