using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using System.Xml.XPath; using Umbraco.Core.Xml; namespace Umbraco.Core { /// /// Extension methods for xml objects /// public static class XmlExtensions { public static bool HasAttribute(this XmlAttributeCollection attributes, string attributeName) { return attributes.Cast().Any(x => x.Name == attributeName); } /// /// Selects a list of XmlNode matching an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The list of XmlNode matching the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable variables) { var av = variables == null ? null : variables.ToArray(); return SelectNodes(source, expression, av); } /// /// Selects a list of XmlNode matching an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The list of XmlNode matching the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable variables) { var av = variables == null ? null : variables.ToArray(); return SelectNodes(source, expression, av); } /// /// Selects a list of XmlNode matching an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The list of XmlNode matching the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) return source.SelectNodes(expression); var iterator = source.CreateNavigator().Select(expression, variables); return XmlNodeListFactory.CreateNodeList(iterator); } /// /// Selects a list of XmlNode matching an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The list of XmlNode matching the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) return source.SelectNodes(expression); var iterator = source.CreateNavigator().Select(expression, variables); return XmlNodeListFactory.CreateNodeList(iterator); } /// /// Selects the first XmlNode that matches an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The first XmlNode that matches the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable variables) { var av = variables == null ? null : variables.ToArray(); return SelectSingleNode(source, expression, av); } /// /// Selects the first XmlNode that matches an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The first XmlNode that matches the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable variables) { var av = variables == null ? null : variables.ToArray(); return SelectSingleNode(source, expression, av); } /// /// Selects the first XmlNode that matches an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The first XmlNode that matches the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) return source.SelectSingleNode(expression); return SelectNodes(source, expression, variables).Cast().FirstOrDefault(); } /// /// Selects the first XmlNode that matches an XPath expression. /// /// A source XmlNode. /// An XPath expression. /// A set of XPathVariables. /// The first XmlNode that matches the XPath expression. /// /// If is null, or is empty, or contains only one single /// value which itself is null, then variables are ignored. /// The XPath expression should reference variables as $var. /// public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) return source.SelectSingleNode(expression); return SelectNodes(source, expression, variables).Cast().FirstOrDefault(); } /// /// Converts from an XDocument to an XmlDocument /// /// /// public static XmlDocument ToXmlDocument(this XDocument xDocument) { var xmlDocument = new XmlDocument(); using (var xmlReader = xDocument.CreateReader()) { xmlDocument.Load(xmlReader); } return xmlDocument; } /// /// Converts from an XmlDocument to an XDocument /// /// /// public static XDocument ToXDocument(this XmlDocument xmlDocument) { using (var nodeReader = new XmlNodeReader(xmlDocument)) { nodeReader.MoveToContent(); return XDocument.Load(nodeReader); } } ///// ///// Converts from an XElement to an XmlElement ///// ///// ///// public static XmlNode ToXmlElement(this XContainer xElement) { var xmlDocument = new XmlDocument(); using (var xmlReader = xElement.CreateReader()) { xmlDocument.Load(xmlReader); } return xmlDocument.DocumentElement; } /// /// Converts from an XmlElement to an XElement /// /// /// public static XElement ToXElement(this XmlNode xmlElement) { using (var nodeReader = new XmlNodeReader(xmlElement)) { nodeReader.MoveToContent(); return XElement.Load(nodeReader); } } public static T AttributeValue(this XElement xml, string attributeName) { if (xml == null) throw new ArgumentNullException("xml"); if (xml.HasAttributes == false) return default(T); if (xml.Attribute(attributeName) == null) return default(T); var val = xml.Attribute(attributeName).Value; var result = val.TryConvertTo(); if (result.Success) return result.Result; return default(T); } public static T AttributeValue(this XmlNode xml, string attributeName) { if (xml == null) throw new ArgumentNullException("xml"); if (xml.Attributes == null) return default(T); if (xml.Attributes[attributeName] == null) return default(T); var val = xml.Attributes[attributeName].Value; var result = val.TryConvertTo(); if (result.Success) return result.Result; return default(T); } public static XElement GetXElement(this XmlNode node) { XDocument xDoc = new XDocument(); using (XmlWriter xmlWriter = xDoc.CreateWriter()) node.WriteTo(xmlWriter); return xDoc.Root; } public static XmlNode GetXmlNode(this XContainer element) { using (var xmlReader = element.CreateReader()) { var xmlDoc = new XmlDocument(); xmlDoc.Load(xmlReader); return xmlDoc.DocumentElement; } } public static XmlNode GetXmlNode(this XContainer element, XmlDocument xmlDoc) { return xmlDoc.ImportNode(element.GetXmlNode(), true); } // this exists because // new XElement("root", "a\nb").Value is "a\nb" but // .ToString(SaveOptions.*) is "a\r\nb" and cannot figure out how to get rid of "\r" // and when saving data we want nothing to change // this method will produce a string that respects the \r and \n in the data value public static string ToDataString(this XElement xml) { var settings = new XmlWriterSettings { OmitXmlDeclaration = true, NewLineHandling = NewLineHandling.None, Indent = false }; var output = new StringBuilder(); using (var writer = XmlWriter.Create(output, settings)) { xml.WriteTo(writer); } return output.ToString(); } } }