⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmltranslator.cs

📁 xhtml到rtf的转换程序!带源码!
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Xml;
using System.Collections;
using System.Drawing;

namespace RichTextBoxSupportsXHTML
{
	/// <summary>
	/// This class extends XmlDocument. It can hold a DOM of any XML document or fragment,
	/// which can be used to translate the XML into other forms. Currently, this class
	/// only supports translation from XML to RTF (Rich Text Format).
	/// </summary>
	public class XmlTranslator : XmlDocument
	{
		private RtfDocument rtfDocument;
		private XmlTextReader reader;
		private ArrayList errors = new ArrayList();

		/// <summary>
		/// Any errors encountered during translation will be contained
		/// in this ArrayList of strings.
		/// </summary>
		public ArrayList Errors
		{
			get
			{
				return errors;
			}
		}

		public XmlTranslator() : base() { }

		/// <summary>
		/// Passing a string of XML code to be translated creates a DOM of the Xml fragment.
		/// </summary>
		/// <param name="xmlText">XML code to be translated.</param>
		public XmlTranslator(string xmlText) : base()
		{
			try
			{
				// All XML code except that contained within the body element is removed.
				xmlText = TrimBody(xmlText);

				// A space is added after all carriage returns to prevent word squishes
				// across line wraps from the input string.
				xmlText = xmlText.Replace("\n", " \n");

				// In case the input string is an XML fragment that contains multiple
				// roots, an additional element is placed around the input string to serve
				// as the undisputed root. Otherwise, the DOM creation would fail.
				reader = new XmlTextReader(
					new System.IO.StringReader("<XmlTranslator_root>" + xmlText + "</XmlTranslator_root>"));

				// All whitespace is preserved.
				reader.WhitespaceHandling = WhitespaceHandling.All;
				this.Load(reader);
			}
			catch (Exception e)
			{
				// If the XML is not well-formed, there may be an exception thrown
				// during creation of the DOM. The DOM will be empty and an error
				// will be added to the Errors property.
				errors.Add("Error creating DOM. " + e.Message);
			}
		}

		/// <summary>
		/// If there is a body element, then all XML code outside of it is removed.
		/// </summary>
		/// <param name="xmlText">XML code to be trimmed.</param>
		/// <returns></returns>
		public string TrimBody(string xmlText)
		{
			string lower = xmlText.ToLower();
			int bodyStart = lower.IndexOf("<body");
			if (bodyStart > 0)
			{
				xmlText = xmlText.Substring(bodyStart);
			}
			lower = xmlText.ToLower();
			int bodyEnd = lower.LastIndexOf("</body>") + 7;
			if (bodyEnd > 7)
			{
				xmlText = xmlText.Substring(0, bodyEnd);
			}

			return xmlText;
		}

		/// <summary>
		/// Initiates translation from XML to RTF (Rich Text Format)
		/// Returns an object representing a RTF document.
		/// </summary>
		/// <returns></returns>
		public RtfDocument ToRtfDocument()
		{
			rtfDocument = new RtfDocument();
			
			// Starting at the placeholding element XmlTranslator_root,
			// the primary translation method is called recursively on all
			// of the nodes in the XML DOM.
			try
			{

				foreach (XmlNode child in this.DocumentElement.ChildNodes)
				{
					rtfDocument.AppendText("{\\pard ");
					TranslateXmlNodeIntoRtfGroup(child, 3);
					rtfDocument.AppendText("}");
				}
			}
			catch (Exception e)
			{
				// Catch any other exceptions during translation.
				errors.Add("Error during translation. " + e.Message);
			}

			return rtfDocument;
		}

		/// <summary>
		/// The primary method responsible for translating XML into RTF code.
		/// It recursively walks the XML DOM tree, building the RTF document
		/// as it goes.
		/// </summary>
		/// <param name="x">The current node to be translated.</param>
		/// <param name="baseFontSize">The XHTML font size (1-7) of the parent element.</param>
		public void TranslateXmlNodeIntoRtfGroup(XmlNode x, int baseFontSize)
		{
			if (x != null)
			{
				// If a node of this type is reached, then its content should be added
				// to the RTF document, and it has no children to recursively translate.
				if (x.Name.ToLower().ToLower() == "#text")
				{
					rtfDocument.AppendText("{" + x.InnerText + "}");
				}
				// Otherwise this node is a tag of some sort, potentially with children
				// that need to be translated. The supported tags and their attributes 
				// are deciphered, and the equivalent RTF control word(s) is(are) added 
				// to the RTF document.
				else
				{
					bool eval = true; // Evaluate this node's children?
					rtfDocument.AppendText("{"); // Begin new RTF group

					if (x.Name.ToLower() == "body")
					{
						foreach (XmlAttribute attribute in x.Attributes)
						{
							if (attribute.Name.ToLower() == "text")
							{
								int index = 0;
								index = rtfDocument.UseColor(TranslateXhtmlColorIntoColorFromArgb(attribute.Value));
								rtfDocument.AppendText("\\cf" + index + " ");
							}
						}
					}
					else if (x.Name.ToLower() == "br")
					{
						rtfDocument.AppendText("{\\par}");
					}
					else if (x.Name.ToLower() == "h1")
					{
						rtfDocument.AppendText("\\b\\fs48\\par ");
						baseFontSize = 6;
					}
					else if (x.Name.ToLower() == "h2")
					{
						rtfDocument.AppendText("\\b\\fs36\\par ");
						baseFontSize = 5;
					}
					else if (x.Name.ToLower() == "h3")
					{
						rtfDocument.AppendText("\\b\\fs27\\par ");
						baseFontSize = 4;
					}
					else if (x.Name.ToLower() == "h4")
					{
						rtfDocument.AppendText("\\b\\fs24\\par ");
						baseFontSize = 3;
					}
					else if (x.Name.ToLower() == "h5")
					{
						rtfDocument.AppendText("\\b\\fs20\\par ");
						baseFontSize = 2;
					}
					else if (x.Name.ToLower() == "h6")
					{
						rtfDocument.AppendText("\\b\\fs15\\par ");
						baseFontSize = 1;
					}
					else if ((x.Name.ToLower() == "b") || (x.Name.ToLower() == "strong"))
					{
						rtfDocument.AppendText("\\b ");
					}
					else if (    (x.Name.ToLower() == "i") 
						|| (x.Name.ToLower() == "em") 
						|| (x.Name.ToLower() == "cite")
						|| (x.Name.ToLower() == "dfn")
						|| (x.Name.ToLower() == "var"))
					{
						rtfDocument.AppendText("\\i ");
					}
					else if (x.Name.ToLower() == "u")
					{
						rtfDocument.AppendText("\\ul ");
					}
					else if ((x.Name.ToLower() == "s") || (x.Name.ToLower() == "strike"))
					{
						rtfDocument.AppendText("\\strike ");
					}
					else if (    (x.Name.ToLower() == "tt")
						|| (x.Name.ToLower() == "pre")
						|| (x.Name.ToLower() == "code")
						|| (x.Name.ToLower() == "samp"))
					{
						int index = rtfDocument.UseFont("Courier New");
						rtfDocument.AppendText("\\f" + index + "\\fs20 ");
						baseFontSize = 2;
					}
					else if (x.Name.ToLower() == "big")
					{
						baseFontSize++;
						rtfDocument.AppendText("\\fs"
							+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize) + " ");
					}
					else if (x.Name.ToLower() == "small")
					{
						baseFontSize--;
						rtfDocument.AppendText("\\fs"
							+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize) + " ");
					}
					else if (x.Name.ToLower() == "a")
					{
						int index = rtfDocument.UseColor(Color.FromArgb(0, 0, 255));
						rtfDocument.AppendText("\\cf" + index + "\\ul ");
					}
					else if (x.Name.ToLower() == "ul")
					{
						rtfDocument.AppendText("\\pn\\pnlvlblt ");
					}
					else if (x.Name.ToLower() == "li")
					{
						rtfDocument.AppendText("\\pnlvlcont\\par\\pnlvlblt ");
					}
					else if (x.Name.ToLower() == "basefont")
					{
						foreach (XmlAttribute attribute in x.Attributes)
						{
							if (attribute.Name.ToLower() == "size")
							{
								baseFontSize = Int32.Parse(attribute.Value);
								rtfDocument.AppendText("\\fs"
									+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize));
							}
						}
					}
					else if (x.Name.ToLower() == "font")
					{
						foreach (XmlAttribute attribute in x.Attributes)
						{
							if (attribute.Name.ToLower() == "face")
							{
								int commaIndex = attribute.Value.IndexOf(',');
								int index = 0;
								if (commaIndex > 0)
								{
									index = rtfDocument.UseFont(attribute.Value.Substring(0, commaIndex));
								}
								else
								{
									index = rtfDocument.UseFont(attribute.Value);
								}
								rtfDocument.AppendText("\\f" + index + " ");
							}
							else if (attribute.Name.ToLower() == "size")
							{
								if (attribute.Value.StartsWith("+"))
								{
									baseFontSize += Int32.Parse(attribute.Value);
									rtfDocument.AppendText("\\fs"
										+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize) + " ");
								}
								else if (attribute.Value.StartsWith("-"))
								{
									baseFontSize -= Int32.Parse(attribute.Value);
									rtfDocument.AppendText("\\fs"
										+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize) + " ");
								}
								else
								{
									baseFontSize = Int32.Parse(attribute.Value);
									rtfDocument.AppendText("\\fs"
										+ TranslateXhtmlFontSizeIntoRtfFontSize(baseFontSize) + " ");
								}
							}
							else if (attribute.Name.ToLower() == "color")
							{
								int index = 0;
								index = rtfDocument.UseColor(TranslateXhtmlColorIntoColorFromArgb(attribute.Value));
								rtfDocument.AppendText("\\cf" + index + " ");
							}
						}
					}
					// Head elements should not be found, but this is just for extra robustness.
					// Comments should not be evaluated.
					else if ((x.Name.ToLower() == "head")
						|| (x.Name.ToLower() == "#comment"))
					{
						eval = false;
					}
					
					if (eval)
					{
						// All known and unknown tags may have the style attribute,
						// which in turn may contain certain properties which will
						// affect the format of descendent elements. This for loop
						// parses the style attribute if one exists on the current node.
						// token[0] == property name; token[1] == property value
						foreach (XmlAttribute attribute in x.Attributes)
						{
							if (attribute.Name.ToLower() == "style")
							{
								char[] semi = {';'};
								string[] tokens = attribute.Value.Split(semi);
								
								for (int i = 0; i < tokens.Length; i++)
								{
									char[] colon = {':'};
									string[] token = tokens[i].Split(colon);

									if (token[0].ToLower().Trim() == "font-family")
									{
										int commaIndex = token[1].Trim().IndexOf(',');
										int index = 0;
										if (commaIndex > 0)
										{
											index = rtfDocument.UseFont(token[1].Substring(0, commaIndex).Trim());
										}
										else
										{
											index = rtfDocument.UseFont(token[1].Trim());
										}
										rtfDocument.AppendText("\\f" + index + " ");
									}
									else if (token[0].ToLower().Trim() == "font-size")
									{
										int rtfFontSize = TranslateStyleFontSizeIntoRtfFontSize(token[1].Trim(), baseFontSize);
										baseFontSize = TranslateRtfFontSizeIntoXhtmlFontSize(rtfFontSize);
										rtfDocument.AppendText("\\fs" + rtfFontSize + " ");
									}
									else if (token[0].ToLower().Trim() == "font-style")
									{
										if (token[1].ToLower().Trim() == "normal")
										{
											rtfDocument.AppendText("\\i0 ");
										}
										else if ((token[1].ToLower().Trim() == "italic")
											|| (token[1].ToLower().Trim() == "oblique"))
										{
											rtfDocument.AppendText("\\i ");
										}
									}
									else if (token[0].ToLower().Trim() == "font-weight")
									{
										if ((token[1].ToLower().Trim() == "normal")
											|| (token[1].ToLower().Trim() == "lighter"))
										{
											rtfDocument.AppendText("\\b0 ");
										}
										else
										{
											rtfDocument.AppendText("\\b ");
										}
									}
									else if (token[0].ToLower().Trim() == "text-align")
									{
										if (token[1].ToLower().Trim() == "right")
										{
											rtfDocument.AppendText("\\qr ");
										}
										else if (token[1].ToLower().Trim() == "center")
										{
											rtfDocument.AppendText("\\qc ");
										}
										else if (token[1].ToLower().Trim() == "justify")
										{
											rtfDocument.AppendText("\\qj ");
										}
										else
										{
											rtfDocument.AppendText("\\ql ");
										}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -