public XElement ConvertToXml(string source) { string processed = string.Empty; HtmlReader reader = new HtmlReader(source); StringBuilder builder = new StringBuilder(); HtmlWriter writer = new HtmlWriter(builder); while (!reader.EOF) writer.WriteNode(reader, true); //XML hates processed = Filter(builder.ToString(),true); XElement result = XElement.Parse(processed); return result; }
public static string Parse(HtmlWriter parent, string name, string value, HtmlWriter writer) { StringBuilder builder = new StringBuilder(); StyleElement element = GetStyleElement(parent, name, writer); StringReader reader = new StringReader(value); System.Collections.Generic.List<string> subElements = new System.Collections.Generic.List<string>(); System.Collections.Generic.List<string> parsedSubElements = new System.Collections.Generic.List<string>(); #region Split elements bool skipSpaces = false; bool skipUntilApos = false; bool skipUntilCloseBracket = false; int thisInt; Char thisChar; while (true) { thisInt = reader.Read(); if (thisInt == -1) { if (builder.Length > 0) subElements.Add(builder.ToString()); break; } thisChar = Convert.ToChar(thisInt); if (skipSpaces && thisChar != ' ') skipSpaces = false; if (!skipSpaces && thisChar == ',') skipSpaces = true; if (skipUntilApos && thisChar == '\'') skipUntilApos = false; if (!skipUntilApos && thisChar == '\'') skipUntilApos = true; if (skipUntilCloseBracket && thisChar == ')') skipUntilCloseBracket = false; if (!skipUntilCloseBracket && thisChar == '(') skipUntilCloseBracket = true; if (thisChar == ' ' && !skipSpaces && !skipUntilApos && !skipUntilCloseBracket) { if (builder.Length > 0) subElements.Add(builder.ToString()); builder.Length = 0; continue; } builder.Append(thisChar); } #endregion #region Parse elements string proposedElement; string proposedElementLower; for (int i = 0; i < subElements.Count && parsedSubElements.Count <= element.MaxSubElements; i++) { proposedElement = subElements[i].Trim(); proposedElementLower = subElements[i].ToLower().Trim(); #region Text try { if ((element.ValidElementTypes & Types.Text) != 0) { if (element.IsValidTextValue(proposedElement.ToLower())) { parsedSubElements.Add(proposedElement.ToLower()); continue; } } } catch { } #endregion #region Url try { if ((element.ValidElementTypes & Types.Url) != 0) { if (proposedElementLower.StartsWith("url(") && proposedElementLower.EndsWith(")")) { string urlUnparsed = proposedElement.Substring(4, proposedElement.Length - 5).Trim(); string surroundChar = ""; if (urlUnparsed.StartsWith("'") && urlUnparsed.EndsWith("'")) { urlUnparsed = urlUnparsed.Substring(1, urlUnparsed.Length - 2); surroundChar = "'"; } else if (urlUnparsed.StartsWith("\"") && urlUnparsed.EndsWith("\"")) { urlUnparsed = urlUnparsed.Substring(1, urlUnparsed.Length - 2); surroundChar = "\""; } string url = element.Parent.ParseAttributeUrl(urlUnparsed, false); if (url.Length > 0) parsedSubElements.Add("url(" + surroundChar + url + surroundChar + ")"); continue; } } } catch { } #endregion #region Percentage try { if ((element.ValidElementTypes & Types.Percentage) != 0) { if (writer.StylePercentageRegex.IsMatch(proposedElement)) { parsedSubElements.Add(proposedElement); continue; } } } catch { } #endregion #region Length try { if ((element.ValidElementTypes & Types.Length) != 0) { if (writer.StyleLengthRegex.IsMatch(proposedElementLower)) { parsedSubElements.Add(proposedElementLower); continue; } } } catch { } #endregion #region Colour try { if ((element.ValidElementTypes & Types.Colour) != 0) { if (writer.AttributeColourRegex.IsMatch(proposedElementLower) || writer.StyleColourRgbRegex.IsMatch(proposedElementLower) || writer.StyleColourNameRegex.IsMatch(proposedElementLower)) { parsedSubElements.Add(proposedElementLower); continue; } } } catch { } #endregion #region Integer try { if ((element.ValidElementTypes & Types.Integer) != 0) { if (writer.StyleIntegerRegex.IsMatch(proposedElement)) { parsedSubElements.Add(proposedElement); continue; } } } catch { } #endregion #region Number try { if ((element.ValidElementTypes & Types.Number) != 0) { if (writer.StyleNumberRegex.IsMatch(proposedElement)) { parsedSubElements.Add(proposedElement); continue; } } } catch { } #endregion #region Shape try { if ((element.ValidElementTypes & Types.Shape) != 0) { if (proposedElementLower.StartsWith("rect(") && proposedElementLower.EndsWith(")")) { string coords = proposedElement.Substring(5, proposedElement.Length - 6).Trim(); string[] coordsAry = coords.Split(','); if (writer.StyleLengthRegex.IsMatch(coordsAry[0].Trim()) && writer.StyleLengthRegex.IsMatch(coordsAry[1].Trim()) && writer.StyleLengthRegex.IsMatch(coordsAry[2].Trim()) && writer.StyleLengthRegex.IsMatch(coordsAry[3].Trim())) { parsedSubElements.Add(proposedElementLower); continue; } } } } catch { } #endregion #region FontSizeLineHeight try { if ((element.ValidElementTypes & Types.FontSizeLineHeight) != 0) { if (proposedElementLower.IndexOf('/') > -1) { string fontSize = proposedElementLower.Substring(0, proposedElementLower.IndexOf('/')); string lineHeight = proposedElementLower.Substring(proposedElementLower.IndexOf('/') + 1); if ((fontSize.Equals("xx-small") || fontSize.Equals("x-small") || fontSize.Equals("small") || fontSize.Equals("medium") || fontSize.Equals("large") || fontSize.Equals("x-large") || fontSize.Equals("xx-large") || fontSize.Equals("smaller") || fontSize.Equals("larger") || writer.StyleLengthRegex.IsMatch(fontSize) || writer.StylePercentageRegex.IsMatch(fontSize)) && (lineHeight.Equals("xx-small") || lineHeight.Equals("x-small") || lineHeight.Equals("small") || lineHeight.Equals("medium") || lineHeight.Equals("large") || lineHeight.Equals("x-large") || lineHeight.Equals("xx-large") || lineHeight.Equals("smaller") || lineHeight.Equals("larger") || writer.StyleNumberRegex.IsMatch(lineHeight) || writer.StyleLengthRegex.IsMatch(lineHeight) || writer.StylePercentageRegex.IsMatch(lineHeight))) { parsedSubElements.Add(proposedElementLower); continue; } } } } catch { } #endregion #region FontFamily try { if ((element.ValidElementTypes & Types.FontFamily) != 0) { string parsedFontFamily = writer.StyleFontFamilyRegex.Replace(proposedElement, String.Empty); if (parsedFontFamily.Length > 0) { parsedSubElements.Add(parsedFontFamily); continue; } } } catch { } #endregion } #endregion #region Build output builder.Length = 0; foreach (string parsedElement in parsedSubElements) { if (builder.Length > 0) builder.Append(" "); builder.Append(parsedElement); } return builder.ToString(); #endregion }
static StyleElement GetStyleElementPrivate(HtmlWriter parent, string name) { #region Element definitions switch (name) { //Extra style elements for dsi tags case "content": return new StyleElement(parent, "text", "icon", "text-under-icon"); // for type=usr, event, venue, place, group, brand case "details": return new StyleElement(parent, "none", "venue", "place", "country"); // for type=event, venue, place case "date": return new StyleElement(parent, "false", "true"); // for type=event case "snip": return new StyleElement(parent, Types.Number); // for type=event case "rollover": return new StyleElement(parent, "true", "false"); // for type=usr, photo case "photo": return new StyleElement(parent, "icon", "thumb", "web"); // for type=photo case "link": return new StyleElement(parent, "true", "false"); case "font-family": return new StyleElement(parent, Types.FontFamily); case "font-style": return new StyleElement(parent, "normal", "italic"); case "font-variant": return new StyleElement(parent, "normal", "small-caps"); case "font-weight": return new StyleElement(parent, "normal", "bold"); case "font-size": return new StyleElement(parent, Types.Percentage | Types.Length, "xx-large", "x-large", "large", "medium", "small", "x-small", "xx-small", "larger", "smaller"); case "font": return new StyleElement(parent, 5, Types.Percentage | Types.Length | Types.FontSizeLineHeight | Types.FontFamily, "normal", "italic", "normal", "small-caps", "normal", "bold", "xx-large", "x-large", "large", "medium", "small", "x-small", "xx-small", "larger", "smaller"); case "color": return new StyleElement(parent, Types.Colour); case "background-color": return new StyleElement(parent, Types.Colour, "transparent"); case "background-image": return new StyleElement(parent, Types.Url, "none"); case "background-repeat": return new StyleElement(parent, "repeat", "repeat-x", "repeat-y", "no-repeat"); case "background-attachment": return new StyleElement(parent, "scroll", "fixed"); case "background-position": return new StyleElement(parent, 2, Types.Length | Types.Percentage, "top", "center", "bottom", "left", "right"); case "background": return new StyleElement(parent, 6, Types.Colour | Types.Url | Types.Length | Types.Percentage, "transparent", "none", "repeat", "repeat-x", "repeat-y", "no-repeat", "scroll", "fixed", "top", "center", "bottom", "left", "right"); case "letter-spacing": return new StyleElement(parent, Types.Length, "normal"); case "text-decoration": return new StyleElement(parent, "none", "underline", "overline", "line-through"); case "vertical-align": return new StyleElement(parent, "sub", "super"); case "text-transform": return new StyleElement(parent, "capitalize", "uppercase", "lowercase", "none"); case "text-align": return new StyleElement(parent, "left", "right", "center", "justify"); case "text-indent": return new StyleElement(parent, Types.Length | Types.Percentage); case "line-height": return new StyleElement(parent, Types.Number | Types.Length | Types.Percentage, "normal"); case "margin-top": return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); case "margin-right": return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); case "margin-bottom": return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); case "margin-left": return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); case "margin": return new StyleElement(parent, 4, Types.Length | Types.Percentage, "auto"); case "padding-top": return new StyleElement(parent, Types.Length | Types.Percentage); case "padding-right": return new StyleElement(parent, Types.Length | Types.Percentage); case "padding-bottom": return new StyleElement(parent, Types.Length | Types.Percentage); case "padding-left": return new StyleElement(parent, Types.Length | Types.Percentage); case "padding": return new StyleElement(parent, 4, Types.Length | Types.Percentage); case "border-top-width": return new StyleElement(parent, Types.Length, "thin", "medium", "thick"); case "border-right-width": return new StyleElement(parent, Types.Length, "thin", "medium", "thick"); case "border-bottom-width": return new StyleElement(parent, Types.Length, "thin", "medium", "thick"); case "border-left-width": return new StyleElement(parent, Types.Length, "thin", "medium", "thick"); case "border-width": return new StyleElement(parent, 4, Types.Length, "thin", "medium", "thick"); case "border-top-color": return new StyleElement(parent, Types.Colour); case "border-right-color": return new StyleElement(parent, Types.Colour); case "border-bottom-color": return new StyleElement(parent, Types.Colour); case "border-left-color": return new StyleElement(parent, Types.Colour); case "border-color": return new StyleElement(parent, 4, Types.Colour); case "border-top-style": return new StyleElement(parent, "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-right-style": return new StyleElement(parent, "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-bottom-style": return new StyleElement(parent, "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-left-style": return new StyleElement(parent, "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-style": return new StyleElement(parent, "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-top": return new StyleElement(parent, 3, Types.Length | Types.Colour, "thin", "medium", "thick", "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-right": return new StyleElement(parent, 3, Types.Length | Types.Colour, "thin", "medium", "thick", "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-bottom": return new StyleElement(parent, 3, Types.Length | Types.Colour, "thin", "medium", "thick", "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border-left": return new StyleElement(parent, 3, Types.Length | Types.Colour, "thin", "medium", "thick", "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "border": return new StyleElement(parent, 3, Types.Length | Types.Colour, "thin", "medium", "thick", "none", "solid", "double", "groove", "ridge", "inset", "outset"); case "float": return new StyleElement(parent, "none", "left", "right"); case "clear": return new StyleElement(parent, "none", "left", "right", "both"); case "display": return new StyleElement(parent, "none", "block", "inline", "list-item"); case "list-style-type": return new StyleElement(parent, "disk", "circle", "square", "decimal", "lower-roman", "upper-roman", "lower-alpha", "upper-alpha", "none"); case "list-style-image": return new StyleElement(parent, Types.Url, "none"); case "list-style-position": return new StyleElement(parent, "inside", "outside"); case "list-style": return new StyleElement(parent, 3, Types.Url, "disk", "circle", "square", "decimal", "lower-roman", "upper-roman", "lower-alpha", "upper-alpha", "none", "inside", "outside"); case "clip": return new StyleElement(parent, Types.Shape, "auto"); case "height": return new StyleElement(parent, Types.Length, "auto"); case "left": return null;// return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); REMOVED case "overflow": return new StyleElement(parent, "visible", "hidden", "scroll", "auto"); case "position": return null; // return new StyleElement(parent, "absolute", "relative", "static"); REMOVED case "top": return null;// return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); REMOVED case "visibility": return new StyleElement(parent, "visible", "hidden", "inherit"); case "width": return new StyleElement(parent, Types.Length | Types.Percentage, "auto"); case "z-index": return new StyleElement(parent, Types.Integer, "auto"); case "page-break-before": return new StyleElement(parent, 2, "auto", "always", "left", "right"); case "page-break-after": return new StyleElement(parent, 2, "auto", "always", "left", "right"); case "cursor": return new StyleElement(parent, "auto", "crosshair", "default", "hand", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help"); default: return null; } #endregion }
public static StyleElement GetStyleElement(HtmlWriter parent, string name, HtmlWriter writer) { #region Get from definition cache if (!writer.StyleElementCache.ContainsKey(name)) writer.StyleElementCache[name] = GetStyleElementPrivate(parent, name); return writer.StyleElementCache[name]; #endregion }
public StyleElement( HtmlWriter parent, Types validElementTypes, params string[] validTextValues) { Parent = parent; MaxSubElements = 1; ValidElementTypes = validElementTypes | Types.Text; ValidTextValues = validTextValues; }
public StyleElement( HtmlWriter parent, int maxSubElements, Types validElementTypes) { Parent = parent; MaxSubElements = maxSubElements; ValidElementTypes = validElementTypes; ValidTextValues = new string[] { }; }
public StyleElement( HtmlWriter parent, int maxSubElements, params string[] validTextValues) { Parent = parent; ValidTextValues = validTextValues; MaxSubElements = maxSubElements; ValidElementTypes = Types.Text; }