using System; using System.Text; using System.IO; using System.Xml; using System.Collections; using System.Text.RegularExpressions; #if AdvTree namespace DevComponents.Tree.TextMarkup #elif DOTNETBAR namespace DevComponents.DotNetBar.TextMarkup #elif SUPERGRID namespace DevComponents.SuperGrid.TextMarkup #elif LAYOUT namespace DevComponents.DotNetBar.Layout.TextMarkup #endif { internal class MarkupParser { #region Private Variables private static string TextElementName = "text"; private static string BodyTag = "body"; #endregion #region Internal Implementation public static BodyElement Parse(string text) { StringBuilder plainText = new StringBuilder(text.Length); BodyElement root = new BodyElement(); root.HasExpandElement = false; MarkupElement currentParent = root; Stack openTags = new Stack(); openTags.Push(root); // Input text is not wrapped into the container tag so we wrap it here text = text.Replace(" ", "{ent_nbsp}"); text = text.Replace("&zwsp;", "{ent_zwsp}"); text = text.Replace("<", "{ent_lt}"); text = text.Replace(">", "{ent_gt}"); text = text.Replace("&", "{ent_amp}"); text = text.Replace("|", "{ent_l}"); text = text.Replace("&", "|"); text = text.Replace("{ent_nbsp}", " "); text = text.Replace("{ent_zwsp}", "&zwsp;"); text = text.Replace("{ent_lt}", "<"); text = text.Replace("{ent_gt}", ">"); StringReader sr = new StringReader("<"+BodyTag+">" + text + ""); #if !DEBUG try #endif { XmlTextReader reader = new XmlTextReader(sr); //reader.EntityHandling = EntityHandling.ExpandCharEntities; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == BodyTag) continue; MarkupElement el = CreateMarkupElement(reader.Name); if (el == null) { reader.Skip(); continue; } else if (el is ExpandElement) root.HasExpandElement = true; if (el is IActiveMarkupElement) root.ActiveElements.Add(el); // Parse any attributes here if (reader.AttributeCount > 0) { el.ReadAttributes(reader); reader.MoveToElement(); } currentParent.Elements.Add(el); if (el is ContainerElement) currentParent = el; if (!reader.IsEmptyElement) openTags.Push(el); } else if (reader.NodeType == XmlNodeType.Text) { if (reader.Value.Length == 1) { TextElement el = CreateMarkupElement(TextElementName) as TextElement; if (reader.Value == " ") { el.TrailingSpace = true; plainText.Append(' '); } else { el.Text = reader.Value; el.Text = el.Text.Replace("|", "&"); el.Text = el.Text.Replace("{ent_l}", "|"); el.Text = el.Text.Replace("{ent_amp}", "&&"); plainText.Append(el.Text+" "); } currentParent.Elements.Add(el); } else { string s = reader.Value; if (s.StartsWith("\r\n")) s = s.TrimStart(new char[] { '\r', '\n' }); s = s.Replace("\r\n", " "); string[] words = s.Split(' '); bool space = false; if (currentParent.Elements.Count > 0 && currentParent.Elements[currentParent.Elements.Count - 1] is NewLine) space = true; for (int i = 0; i < words.Length; i++) { if (words[i].Length == 0) { if (space) continue; space = true; } else space = false; TextElement el = CreateMarkupElement(TextElementName) as TextElement; el.Text = words[i].Replace("|","&"); el.Text = el.Text.Replace("{ent_l}", "|"); el.Text = el.Text.Replace("{ent_amp}", "&&"); plainText.Append(el.Text + " "); if (i < words.Length - 1) { el.TrailingSpace = true; space = true; } currentParent.Elements.Add(el); } } } else if (reader.NodeType == XmlNodeType.Whitespace) { if (reader.Value.IndexOf(' ') >= 0) { TextElement el = CreateMarkupElement(TextElementName) as TextElement; el.TrailingSpace = true; currentParent.Elements.Add(el); } } else if (reader.NodeType == XmlNodeType.EntityReference) { TextElement el = CreateMarkupElement(TextElementName) as TextElement; if (reader.Name == "nbsp") { el.TrailingSpace = true; } else if (reader.Name == "zwsp") { el.TrailingSpace = false; } else el.Text = reader.Name; el.EnablePrefixHandling = false; currentParent.Elements.Add(el); } else if (reader.NodeType == XmlNodeType.EndElement) { MarkupElement el = openTags.Pop() as MarkupElement; if (el != currentParent) { currentParent.Elements.Add(new EndMarkupElement(el)); } else { if (currentParent != root) currentParent = currentParent.Parent; } } } } #if !DEBUG catch { return null; } #endif root.PlainText = plainText.ToString(); return root; } public static MarkupElement CreateMarkupElement(string elementName) { if (elementName == "b" || elementName == "strong") return new Strong(); else if (elementName == "i" || elementName == "em") return new Italic(); else if (elementName == "u") return new Underline(); else if (elementName == "br") return new NewLine(); else if (elementName == "expand") return new ExpandElement(); else if (elementName == "a") return new HyperLink(); else if (elementName == "p") return new Paragraph(); else if (elementName == "div") return new Div(); else if (elementName == "span") return new Span(); else if (elementName == "img") return new ImageElement(); else if (elementName == "h1") return new Heading(); else if (elementName == "h2") return new Heading(2); else if (elementName == "h3") return new Heading(3); else if (elementName == "h4") return new Heading(4); else if (elementName == "h5") return new Heading(5); else if (elementName == "h6") return new Heading(6); else if (elementName == "font") return new FontElement(); else if (elementName == "s" || elementName == "strike") return new Strike(); else if (elementName == TextElementName) return new TextElement(); else if (elementName == "symbol") return new SymbolElement(); return null; } /// /// Tests whether input text could be markup text. /// /// Text to test. /// true if text could be markup, otherwise false public static bool IsMarkup(ref string text) { if (text == null || text.IndexOf("") < 0) return false; return true; } internal static string RemoveExpand(string text) { return Regex.Replace(text, "", "", RegexOptions.IgnoreCase); } #endregion } }