예제 #1
0
        /// <summary>
        ///     Evaluates an XPath expression against an XContainer (which is an XElement and an XDocument)
        ///     and returns an sequence of strings the expression resulted in.
        ///     It is recommended to pass an XDocument, but if an XElement is submitted, it will be parsed to
        ///     an XDocument so the XPath expression evaluates as expected.
        /// </summary>
        /// <param name="xContainer">
        ///     The XElement or XDocument the XPath will be applied to.
        ///     NOTE: if an XElement is submitted, it will be parsed into an XDocument before the XPath expression is evaluated.
        /// </param>
        /// <param name="xPath">A string containing the XPath expression to evaluate with.</param>
        /// <param name="exceptionMessage">The exception message string.</param>
        /// <returns>
        ///     Returns an IEnumerable of strings containing all resulting element and attribute values evaluated with the XPath
        ///     expression.
        ///     If nothing was found, then an empty enumerable is returned.
        /// </returns>
        public static IEnumerable <string> SelectXPathValues(this XContainer xContainer, string xPath,
                                                             out string exceptionMessage)
        {
            exceptionMessage = string.Empty;

            if (xContainer == null || xPath.HasNoValue())
            {
                return(Enumerable.Empty <string>());
            }

            var errorSb = new Lazy <StringBuilder>();

            var results = Enumerable.Empty <string>();

            if (xPath.HasNoValue())
            {
                return(results);
            }

            // if the container is an element, parse it to a document so the xpath evaluation works as expected.
            if (xContainer is XElement)
            {
                xContainer = XDocument.Parse(xContainer.ToString());
            }

            var manager = new XmlNamespaceManager(xContainer.CreateNavigator().NameTable);

            IEnumerable <object> xObjects;
            object xDocXPathEvaluate;

            try
            {
                xDocXPathEvaluate = xContainer.XPathEvaluate(xPath, manager);
            }
            catch (Exception ex)
            {
                var xmlMessage = new XElement("exception", new XElement("xPath", xPath),
                                              new XElement("message", ex.Message));
                errorSb.Value.AppendFormat("Error Evaluating XPath: {0}.  ", xmlMessage);
                return(results);
            }

            var xDocXPathEvaluateAsIEnumerable = xDocXPathEvaluate as IEnumerable <object>;

            if (xDocXPathEvaluateAsIEnumerable != null)
            {
                xObjects = xDocXPathEvaluateAsIEnumerable;
            }
            else
            {
                return new List <string> {
                           xDocXPathEvaluate.ToString()
                }
            };

            if (xObjects.NoItems())
            {
                errorSb.Value.AppendFormat("Xpath did not find results: {0}", xPath);
            }

            // return the evaluated strings
            results = (from e in xObjects.OfType <XElement>()
                       select(string) e)
                      .Concat(
                from e in xObjects.OfType <XAttribute>()
                select(string) e);

            if (errorSb.IsValueCreated)
            {
                exceptionMessage = errorSb.Value.ToString();
            }

            return(results);
        }