Пример #1
0
        /// <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;
        }
Пример #2
0
 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);
 }