/// <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); }