using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Xml; using Umbraco.Core.IO; namespace Umbraco.Core { /// /// The XmlHelper class contains general helper methods for working with xml in umbraco. /// public class XmlHelper { public static string StripDashesInElementOrAttributeNames(string xml) { using (var outputms = new MemoryStream()) { using (TextWriter outputtw = new StreamWriter(outputms)) { using (var ms = new MemoryStream()) { using (var tw = new StreamWriter(ms)) { tw.Write(xml); tw.Flush(); ms.Position = 0; using (var tr = new StreamReader(ms)) { bool IsInsideElement = false, IsInsideQuotes = false; int ic = 0; while ((ic = tr.Read()) != -1) { if (ic == (int)'<' && !IsInsideQuotes) { if (tr.Peek() != (int)'!') { IsInsideElement = true; } } if (ic == (int)'>' && !IsInsideQuotes) { IsInsideElement = false; } if (ic == (int)'"') { IsInsideQuotes = !IsInsideQuotes; } if (!IsInsideElement || ic != (int)'-' || IsInsideQuotes) { outputtw.Write((char)ic); } } } } } outputtw.Flush(); outputms.Position = 0; using (TextReader outputtr = new StreamReader(outputms)) { return outputtr.ReadToEnd(); } } } } /// /// Imports a XML node from text. /// /// The text. /// The XML doc. /// public static XmlNode ImportXmlNodeFromText(string text, ref XmlDocument xmlDoc) { xmlDoc.LoadXml(text); return xmlDoc.FirstChild; } /// /// Opens a file as a XmlDocument. /// /// The relative file path. ei. /config/umbraco.config /// Returns a XmlDocument class public static XmlDocument OpenAsXmlDocument(string filePath) { var reader = new XmlTextReader(IOHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All}; var xmlDoc = new XmlDocument(); //Load the file into the XmlDocument xmlDoc.Load(reader); //Close off the connection to the file. reader.Close(); return xmlDoc; } /// /// creates a XmlAttribute with the specified name and value /// /// The xmldocument. /// The name of the attribute. /// The value of the attribute. /// a XmlAttribute public static XmlAttribute AddAttribute(XmlDocument xd, string name, string value) { var temp = xd.CreateAttribute(name); temp.Value = value; return temp; } /// /// Creates a text XmlNode with the specified name and value /// /// The xmldocument. /// The node name. /// The node value. /// a XmlNode public static XmlNode AddTextNode(XmlDocument xd, string name, string value) { var temp = xd.CreateNode(XmlNodeType.Element, name, ""); temp.AppendChild(xd.CreateTextNode(value)); return temp; } /// /// Creates a cdata XmlNode with the specified name and value /// /// The xmldocument. /// The node name. /// The node value. /// A XmlNode public static XmlNode AddCDataNode(XmlDocument xd, string name, string value) { var temp = xd.CreateNode(XmlNodeType.Element, name, ""); temp.AppendChild(xd.CreateCDataSection(value)); return temp; } /// /// Gets the value of a XmlNode /// /// The XmlNode. /// the value as a string public static string GetNodeValue(XmlNode n) { var value = string.Empty; if (n == null || n.FirstChild == null) return value; value = n.FirstChild.Value ?? n.InnerXml; return value.Replace("", "", "]]>"); } /// /// Determines whether the specified string appears to be XML. /// /// The XML string. /// /// true if the specified string appears to be XML; otherwise, false. /// public static bool CouldItBeXml(string xml) { if (!string.IsNullOrEmpty(xml)) { xml = xml.Trim(); if (xml.StartsWith("<") && xml.EndsWith(">")) { return true; } } return false; } /// /// Splits the specified delimited string into an XML document. /// /// The data. /// The separator. /// Name of the root. /// Name of the element. /// Returns an System.Xml.XmlDocument representation of the delimited string data. public static XmlDocument Split(string data, string[] separator, string rootName, string elementName) { return Split(new XmlDocument(), data, separator, rootName, elementName); } /// /// Splits the specified delimited string into an XML document. /// /// The XML document. /// The delimited string data. /// The separator. /// Name of the root node. /// Name of the element node. /// Returns an System.Xml.XmlDocument representation of the delimited string data. public static XmlDocument Split(XmlDocument xml, string data, string[] separator, string rootName, string elementName) { // load new XML document. xml.LoadXml(string.Concat("<", rootName, "/>")); // get the data-value, check it isn't empty. if (!string.IsNullOrEmpty(data)) { // explode the values into an array var values = data.Split(separator, StringSplitOptions.None); // loop through the array items. foreach (string value in values) { // add each value to the XML document. var xn = XmlHelper.AddTextNode(xml, elementName, value); xml.DocumentElement.AppendChild(xn); } } // return the XML node. return xml; } /// /// Return a dictionary of attributes found for a string based tag /// /// /// public static Dictionary GetAttributesFromElement(string tag) { var m = Regex.Matches(tag, "(?\\S*)=\"(?[^\"]*)\"", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); // fix for issue 14862: return lowercase attributes for case insensitive matching var d = m.Cast().ToDictionary(attributeSet => attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet => attributeSet.Groups["attributeValue"].Value.ToString()); return d; } } }