// --------------------------------------------------------------------- // // Private Methods // // --------------------------------------------------------------------- #region Private Methods /// <summary> /// Processes a root level element of XAML (normally it's FlowDocument element). /// </summary> /// <param name="xamlReader"> /// XmlTextReader for a source xaml. /// </param> /// <param name="htmlWriter"> /// XmlTextWriter producing resulting html /// </param> private static bool WriteFlowDocument(XmlTextReader xamlReader, ISgmlWriter htmlWriter) { if (!ReadNextToken(xamlReader)) { // Xaml content is empty - nothing to convert return false; } if (xamlReader.NodeType != XmlNodeType.Element || xamlReader.Name != "FlowDocument") { // Root FlowDocument elemet is missing return false; } // Create a buffer StringBuilder for collecting css properties for inline STYLE attributes // on every element level (it will be re-initialized on every level). StringBuilder inlineStyle = new StringBuilder(); //htmlWriter.WriteStartElement("HTML"); //htmlWriter.WriteStartElement("BODY"); WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle); WriteElementContent(xamlReader, htmlWriter, inlineStyle); //htmlWriter.WriteEndElement(); //htmlWriter.WriteEndElement(); return true; }
/// <summary> /// Converts a xaml element into an appropriate html element. /// </summary> /// <param name="xamlReader"> /// On entry this XmlTextReader must be on Element start tag; /// on exit - on EndElement tag. /// </param> /// <param name="htmlWriter"> /// May be null, in which case we are skipping xaml content /// without producing any html output /// </param> /// <param name="inlineStyle"> /// StringBuilder used for collecting css properties for inline STYLE attributes on every level. /// </param> private static void WriteElement(XmlTextReader xamlReader, ISgmlWriter htmlWriter, StringBuilder inlineStyle) { Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); if (htmlWriter == null) { // Skipping mode; recurse into the xaml element without any output WriteElementContent(xamlReader, /*htmlWriter:*/null, null); } else { string htmlElementName = null; switch (xamlReader.Name) { case "Run": case "Span": htmlElementName = "SPAN"; break; case "InlineUIContainer": htmlElementName = "SPAN"; break; case "Bold": htmlElementName = "B"; break; case "Italic": htmlElementName = "I"; break; case "Paragraph": htmlElementName = "P"; break; case "BlockUIContainer": htmlElementName = "DIV"; break; case "Section": htmlElementName = "DIV"; break; case "Table": htmlElementName = "TABLE"; break; case "TableColumn": htmlElementName = "COL"; break; case "TableRowGroup": htmlElementName = "TBODY"; break; case "TableRow": htmlElementName = "TR"; break; case "TableCell": htmlElementName = "TD"; break; case "List": string marker = xamlReader.GetAttribute("MarkerStyle"); if (marker == null || marker == "None" || marker == "Disc" || marker == "Circle" || marker == "Square" || marker == "Box") { htmlElementName = "UL"; } else { htmlElementName = "OL"; } break; case "ListItem": htmlElementName = "LI"; break; default: htmlElementName = null; // Ignore the element break; } if (htmlWriter != null && htmlElementName != null) { htmlWriter.Element(htmlElementName); WriteFormattingProperties(xamlReader, htmlWriter, inlineStyle); WriteElementContent(xamlReader, htmlWriter, inlineStyle); htmlWriter.ElementEnd(); } else { // Skip this unrecognized xaml element WriteElementContent(xamlReader, /*htmlWriter:*/null, null); } } }
/// <summary> /// Reads attributes of the current xaml element and converts /// them into appropriate html attributes or css styles. /// </summary> /// <param name="xamlReader"> /// XmlTextReader which is expected to be at XmlNodeType.Element /// (opening element tag) position. /// The reader will remain at the same level after function complete. /// </param> /// <param name="htmlWriter"> /// XmlTextWriter for output html, which is expected to be in /// after WriteStartElement state. /// </param> /// <param name="inlineStyle"> /// String builder for collecting css properties for inline STYLE attribute. /// </param> private static void WriteFormattingProperties(XmlTextReader xamlReader, ISgmlWriter htmlWriter, StringBuilder inlineStyle) { Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); // Clear string builder for the inline style inlineStyle.Remove(0, inlineStyle.Length); if (!xamlReader.HasAttributes) { return; } bool borderSet = false; while (xamlReader.MoveToNextAttribute()) { string css = null; switch (xamlReader.Name) { // Character fomatting properties // ------------------------------ case "Background": css = "background-color:" + ParseXamlColor(xamlReader.Value) + ";"; break; case "FontFamily": css = "font-family:" + xamlReader.Value + ";"; break; case "FontStyle": css = "font-style:" + xamlReader.Value.ToLower() + ";"; break; case "FontWeight": css = "font-weight:" + xamlReader.Value.ToLower() + ";"; break; case "FontStretch": break; case "FontSize": css = "font-size:" + xamlReader.Value + ";"; break; case "Foreground": css = "color:" + ParseXamlColor(xamlReader.Value) + ";"; break; case "TextDecorations": css = "text-decoration:underline;"; break; case "TextEffects": break; case "Emphasis": break; case "StandardLigatures": break; case "Variants": break; case "Capitals": break; case "Fraction": break; // Paragraph formatting properties // ------------------------------- case "Padding": css = "padding:" + ParseXamlThickness(xamlReader.Value) + ";"; break; case "Margin": css = "margin:" + ParseXamlThickness(xamlReader.Value) + ";"; break; case "BorderThickness": css = "border-width:" + ParseXamlThickness(xamlReader.Value) + ";"; borderSet = true; break; case "BorderBrush": css = "border-color:" + ParseXamlColor(xamlReader.Value) + ";"; borderSet = true; break; case "LineHeight": break; case "TextIndent": css = "text-indent:" + xamlReader.Value + ";"; break; case "TextAlignment": css = "text-align:" + xamlReader.Value + ";"; break; case "IsKeptTogether": break; case "IsKeptWithNext": break; case "ColumnBreakBefore": break; case "PageBreakBefore": break; case "FlowDirection": break; // Table attributes // ---------------- case "Width": css = "width:" + xamlReader.Value + ";"; break; case "ColumnSpan": htmlWriter.Attribute("COLSPAN", xamlReader.Value); break; case "RowSpan": htmlWriter.Attribute("ROWSPAN", xamlReader.Value); break; } if (css != null) { inlineStyle.Append(css); } } if (borderSet) { inlineStyle.Append("border-style:solid;mso-element:para-border-div;"); } // Return the xamlReader back to element level xamlReader.MoveToElement(); Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); }
/// <summary> /// Reads a content of current xaml element, converts it /// </summary> /// <param name="xamlReader"> /// XmlTextReader which is expected to be at XmlNodeType.Element /// (opening element tag) position. /// </param> /// <param name="htmlWriter"> /// May be null, in which case we are skipping the xaml element; /// witout producing any output to html. /// </param> /// <param name="inlineStyle"> /// StringBuilder used for collecting css properties for inline STYLE attribute. /// </param> private static void WriteElementContent(XmlTextReader xamlReader, ISgmlWriter htmlWriter, StringBuilder inlineStyle) { Debug.Assert(xamlReader.NodeType == XmlNodeType.Element); bool elementContentStarted = false; if (xamlReader.IsEmptyElement) { if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0) { // Output STYLE attribute and clear inlineStyle buffer. htmlWriter.Attribute("STYLE", inlineStyle.ToString()); inlineStyle.Remove(0, inlineStyle.Length); } elementContentStarted = true; } else { while (ReadNextToken(xamlReader) && xamlReader.NodeType != XmlNodeType.EndElement) { switch (xamlReader.NodeType) { case XmlNodeType.Element: if (xamlReader.Name.Contains(".")) { AddComplexProperty(xamlReader, inlineStyle); } else { if (htmlWriter != null && !elementContentStarted && inlineStyle.Length > 0) { // Output STYLE attribute and clear inlineStyle buffer. htmlWriter.Attribute("STYLE", inlineStyle.ToString()); inlineStyle.Remove(0, inlineStyle.Length); } elementContentStarted = true; WriteElement(xamlReader, htmlWriter, inlineStyle); } Debug.Assert(xamlReader.NodeType == XmlNodeType.EndElement || xamlReader.NodeType == XmlNodeType.Element && xamlReader.IsEmptyElement); break; case XmlNodeType.Comment: if (htmlWriter != null) { if (!elementContentStarted && inlineStyle.Length > 0) { htmlWriter.Attribute("STYLE", inlineStyle.ToString()); } htmlWriter.Comment(xamlReader.Value); } elementContentStarted = true; break; case XmlNodeType.CDATA: case XmlNodeType.Text: case XmlNodeType.SignificantWhitespace: if (htmlWriter != null) { if (!elementContentStarted && inlineStyle.Length > 0) { htmlWriter.Attribute("STYLE", inlineStyle.ToString()); } htmlWriter.Value(xamlReader.Value); } elementContentStarted = true; break; } } Debug.Assert(xamlReader.NodeType == XmlNodeType.EndElement); } }
public HtmlWriterWrapper(ISgmlWriter writer) { _writer = writer; }