Flex: Export valid HTML from the RichTextEditor

A recent post on the Flex Coders forum prompted me to create a method to clean up the HTML code produced by the Flex RichTextEditor component. Typically, the code that is produced looks like this from the line:

This is <b> Bold </b> text.

<P ALIGN="LEFT">
<FONT FACE="Verdana" SIZE="10" COLOR="#0B333C">
This is <b> Bold </b>text.
</FONT>
</P>

Now that is a lot of extra code and some of it, though ignored by the browser, is just code used only by Flex (or Flash). What is needed is a way to clean the code and make it more standard so you can store in the database and use in more places than just Flex. Using RegExp, I created a small function that strips out the invalid code and leaves:

 private function cleanHTML(str:String):String
 {
	var pattern:RegExp = //g;
	var str:String = str.replace(pattern, "");
	pattern = /<font>/g;
	str = str.replace(pattern, "");
	pattern = //g;
	str = str.replace(pattern, "");
	pattern = //g;
	str = str.replace(pattern, "");
	return str;
}

The function produces the following valid HTML code:

<p Align="LEFT">This is <B> Bold </B> text.</p>

Using a modified version of the same function, you could also change the code to lowercase or add span tags to replace the formatting that we removed. This gives you much more control over the way your text will be displayed in applications outside of Flex. Perhaps one day Adobe will address this issue with invalid HTML that has been a burden of working with Flash since the early days of Flash. You can view the orignal Flex Coder’s discussion

Flex Coders Original Post

Additional discussions of this topic:

Keith Collins
Alexology

- Mister

About these ads

57 thoughts on “Flex: Export valid HTML from the RichTextEditor

  1. Awesome! I was in quite the quandary on this one… on a side note… it is import to escape the forward slashes inside the html tags…

    pattern = //g;
    should be
    pattern = //g;

  2. thank you for the code.
    I’ve tried it and added some extra functionality.

    private function cleanHTML(str:String):String
    {
                   var pattern:RegExp = //g;
                   var str:String = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = /&lt;A HREF/g;
                   str = str.replace(pattern, &quot;&lt;a href&quot;);
                   pattern = //g;
                   str = str.replace(pattern, "</a>");
                   pattern= /TARGET="_blank"/g;
                   str = str.replace(pattern, "rel=\"external\" ");
                   pattern = /<I>/g;
                   str = str.replace(pattern, "<em>");
                   pattern = //g;
                   str = str.replace(pattern, "</em>");
                   pattern = /<B>/g;
                   str = str.replace(pattern, "<strong>");
                   pattern = //g;
                   str = str.replace(pattern, "</strong>");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   return str;
    }
    

    so now it’s XHTML1.1 approved.

    greets
    johan

  3. Hey Johan,

    Your code works great, but wraps each list item in it’s own unordered list (if that’s the case). This will fix it (put it at the end). It assumes you’re not putting 2 unordered lists back to back.


    pattern= //g;
    str = str.replace(pattern, "");

    Cheers,
    Aaron

  4. Sorry for the last post , apparently this form doesnt change htmlspecialchars

    here is the fixed post

    For those those of you wondering what happened to the <FONT> tags heres the answer this pattern will replace the <FONT> tag with the <span> tag change the attribute to styles making it xhtml compliant .
    Just replace the current font Regular Expressions (patten) with these

    pattern = //g;
     str = str.replace(pattern, "");
     pattern = //g;
     str = str.replace(pattern, "");
    
  5. your font fix doesn’t always work because not always are the color size and face present.
    I had to write a few more replaces to take care of that. Also, I save to database after running cleanHTML, but when I load from database I need to uncleanHTML… basically do the reverse. Otherwise it won’t recover it. However textformat was non-reversable. Luckily flash doesn’t require it be there. So why does it write it? The world may never know.

    Here’s my reverse in case you need it and want to copy paste:

    private function uncleanHTML(str:String):String
    		{
                   var pattern:RegExp = //g;
    
     			   var str:String = str.replace(pattern, "");
    
                   pattern = //g;
    
     			   str = str.replace(pattern, "");
    
                   pattern = //g;
    
     			   str = str.replace(pattern, "");
    
                   pattern = //g;
    
     			   str = str.replace(pattern, "");
    
    
    			   pattern = //g;
    
    			   str = str.replace(pattern, "");
    
                   pattern = /<a>/g;
    
                   str = str.replace(pattern, "</A>");
    
                   pattern= /rel="external" /g;
    
                   str = str.replace(pattern, "TARGET=\"_blank\"");
    
                   pattern = /<em>/g;
    
                   str = str.replace(pattern, "<I>");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "</I>");
    
                   pattern = /<strong>/g;
    
                   str = str.replace(pattern, "<B>");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "</B>");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
                   pattern= //g;
    
                   str = str.replace(pattern, "");
    
                   pattern= //g;
    
                   str = str.replace(pattern, "");
    
                   pattern= //g;
    
                   str = str.replace(pattern, "");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
                   pattern = //g;
    
                   str = str.replace(pattern, "");
    
    
                   return str;
    
              }
    

    Cheers =D

  6. Thanks for your contribution to the post. One day I should compile all the code people have contributed and roll it into a new HTML text editor for Flex.

  7. Hi all, bit of a newb here. Just dropped the code in my very basic app between the mx:script tags, registered loads of errors and now whenever i make a change to the app and re-run it, the changes i have made don’t appear. It just runs the old version. Have I put the code in the right place? Sorry I know this is very basic stuff, but thanks for reading. Even better would some button code passing in the parameter to the function. Thanx again!

  8. Hi This is prefect for a project that I am working on! But I can not get it to work. I put the function between the script tags but how do I make it run. I am new to Flex.

    Thanks

  9. In my case I needed to convert back and forth between flex-HTML and XHTML. I’m using the following functions in a util file to do so.

    static public function convertFromXHtml(str:String):String
                   {
                           var pattern:RegExp;
    
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = /color:(.*?);/g;
                           str = str.replace(pattern, "COLOR=\"$1\" ");
                           pattern = /font-size:(.*?)px;/g;
                           str = str.replace(pattern, "SIZE=\"$1\" ");
                           pattern = /font-family:(.*?);/g;
                           str = str.replace(pattern, "FACE=\"$1\" ");
                           pattern = /text-align:(.*?);/g;
                           str = str.replace(pattern, "ALIGN=\"$1\" ");
    
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           pattern= //g;
                           str = str.replace(pattern, "");
                           pattern= //g;
                           str = str.replace(pattern, "");
                           pattern= //g;
                           str = str.replace(pattern, "");
    
                           pattern = /<em>/g;
                           str = str.replace(pattern, "<I>");
                           pattern = //g;
                           str = str.replace(pattern, "</I>");
                           pattern = /<strong>/g;
                           str = str.replace(pattern, "<B>");
                           pattern = //g;
                           str = str.replace(pattern, "</B>");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           // Remove extra white space
                           pattern = /  /g;
                           str = str.replace(pattern, " ");
    
                           return str;
                   }
    
                   static public function convertToXHtml(str:String):String
                   {
                           var pattern:RegExp;
    
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           pattern = /COLOR=\"(.*?)\"/g;
                           str = str.replace(pattern, "color:$1;");
    
                           pattern = /SIZE=\"(.*?)\"/g;
                           str = str.replace(pattern, "font-size:$1px;");
    
                           pattern = /FACE=\"(.*?)\"/g;
                           str = str.replace(pattern, "font-family:$1;");
    
                           pattern = /ALIGN=\"(.*?)\"/g;
                           str = str.replace(pattern, "text-align:$1;");
    
                           pattern = /LETTERSPACING=\".*?\"/g;
                           str = str.replace(pattern, "");
    
                           pattern = /KERNING=\".*?\"/g;
                           str = str.replace(pattern, "");
    
                           pattern = //g;
                           str = str.replace(pattern, "");
    
    
                           pattern= //g;
                           str = str.replace(pattern, "");
                           pattern= //g;
                           str = str.replace(pattern, "");
                           pattern= //g;
                           str = str.replace(pattern, "");
    
                           pattern = /<I>/g;
                           str = str.replace(pattern, "<em>");
                           pattern = //g;
                           str = str.replace(pattern, "</em>");
                           pattern = /<B>/g;
                           str = str.replace(pattern, "<strong>");
                           pattern = //g;
                           str = str.replace(pattern, "</strong>");
                           pattern = //g;
                           str = str.replace(pattern, "");
                           pattern = //g;
                           str = str.replace(pattern, "");
    
                           return str;
                   }
    
  10. I think, You all are wrong. It’s not a good place to use regular expresion. It’s a good place to use XSLT. But we doesn’t have it.
    I sugest use XML trawerse:

    private function cleanHtml(str:String):String {
      // Create XML document
      var xml:XML = XML(""+str+"");
    
      // temporary
      var t1:XML;
      var t2:XML;
    
      // Remove all TEXTFORMAT
      for( t1 = xml..TEXTFORMAT[0]; t1 != null; t1 = xml..TEXTFORMAT[0] ) {
        t1.parent().replace( t1.childIndex(), t1.children() );
      }
    
      // Find all ALIGN and add STYLE
      for each ( t1 in xml..@ALIGN ) {
        t2 = t1.parent();
        t2.@STYLE = "text-align: " + t1 + "; " + t2.@STYLE;
      }
    
      // Find all FACE and add STYLE
      for each ( t1 in xml..@FACE ) {
        t2 = t1.parent();
        t2.@STYLE = "font-family: " + t1 + "; " + t2.@STYLE;
      }
    
      // Find all SIZE and add STYLE
      for each ( t1 in xml..@SIZE ) {
        t2 = t1.parent();
        t2.@STYLE = "font-size: " + t1 + "px; " + t2.@STYLE;
      }
    
      // Find all COLOR and add STYLE
      for each ( t1 in xml..@COLOR ) {
        t2 = t1.parent();
        t2.@STYLE = "color: " + t1 + "; " + t2.@STYLE;
      }
    
      return xml.children().toXMLString();
    }
    

    Tested in IE7, Firefox, Opera

  11. Pingback: CustomRichTextEditor with XHTML text | Axelology

  12. Hi Guys, thanks for the regexp code. My problem is a little different.

    I’m trying to get a TextArea to hold more than one embedded font family, but setStyle only allows me one font family. In addition, the use of setStyle overrides all the htmltext tags.

    What I’d like to do is replace the FontFamily tags with a new value. A typical html tag is:

    This is the theme to Garry's Show,The theme to Garry's show.Garry called me up and asked if I would right his theme song.

    Now I’d like to use a regular expression to replace all the font tags with a new FontFamily. how can I write that?

  13. Great code but I still have a problem.
    I pass accent characters (ò à è é) to php/mysql from the richTextEditor and I have several errors…

    What should I do?
    Roberto

  14. private function cleanHTML(str:String):String{
                   var pattern:RegExp = //g;
                   var str:String = str.replace(pattern, "");
                   pattern = //g;
    			   str = str.replace(pattern, "");
    			   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = /&lt;A HREF/g;
                   str = str.replace(pattern, "&lt;a href");
                   pattern = //g;
                   str = str.replace(pattern, "</a>");
                   pattern= /TARGET="_blank"/g;
                   str = str.replace(pattern, "rel=\"external\" ");
                   pattern = /<I>/g;
                   str = str.replace(pattern, "<em>");
                   pattern = //g;
                   str = str.replace(pattern, "</em>");
                   pattern = /<B>/g;
                   str = str.replace(pattern, "<strong>");
                   pattern = //g;
                   str = str.replace(pattern, "</strong>");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern= //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g
                    str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   pattern = //g;
                   str = str.replace(pattern, "");
                   return str;
    			}
    
  15. Pingback: Custom RichTextEditor — Thanks, Mister!

  16. A whole lot of information seems to be stripped out of many of the posts above. For example, in the first post by Lukas Ruebbelke, he describes that:
    pattern = //g;
    should be
    pattern = //g;

    ???

    it continues in other posts, in descriptions of convertFromXHtml, for example, with reams of lines of:

    [as]str = str.replace(pattern, “”);
    pattern= //g;[/as]

    i’m trying to hunt down a convertFromXHtml method. Can anyone with a copy of this repost or link somewhere where it can be seen in full?

  17. This version will maintain the formatting (styles)

    private function cleanHTML(str:String):String
    		{
    			var newStr:String;
    			var pattern:RegExp = //g;
    			var str:String = str.replace(pattern, "");
    
    			pattern = /ALIGN="/g;
    			var str:String = str.replace(pattern, 'style=" text-align: ');
    
    
    			pattern = /"&gt;&lt;FONT\sFACE?="/g;
    			str = str.replace(pattern, '; font-family: ');
    
    			pattern = /"\sSIZE?="/g;
    			str = str.replace(pattern, '; font-size: ');
    
    			pattern = /"\sCOLOR="/g;
    			str = str.replace(pattern, 'px; color: ');
    
    
    			pattern = /&lt;FONT\sFACE?="/g;
    			newStr = str.replace(pattern, '; font-familly: ');
                var replaced:Boolean = true;
    
                do{
               		replaced = false;
    				if(newStr != str)     //This is if there more occurence of FACE
    				{
    					str = str.replace(pattern, '&lt;span style=" font-size: '); //REPLACE SIZE AND ADD STYLE
    
    	            		pattern = /"\sCOLOR="/g;
    	                	str = str.replace(pattern, '; color: '); // REPLACE COLOR
    	                	replaced = true;
    
    	            	}
    	            	else  //No FACE NO SIZE
    	            	{
    	            		pattern = /&lt;span style=" color: '); // REPLACE COLOR
    	                	replaced = true;
    	            	}
    
    	              }
                }while(replaced == false)
    
    
    			pattern = /"\sLETTERSPACING="\d+" KERNING="\d+"/g;
    			str = str.replace(pattern, ';" ');
    
    			pattern = //g;
    			str = str.replace(pattern, "");
    			pattern = /&lt;A HREF/g;
    			str = str.replace(pattern, "&lt;a href");
    			pattern = //g;
    			str = str.replace(pattern, "</a>");
                  // pattern= /TARGET="_blank"/g;
                  // str = str.replace(pattern, "rel=\"external\" ");
                   pattern = /<I>/g;
    			str = str.replace(pattern, "<em>");
    			pattern = //g;
    			str = str.replace(pattern, "</em>");
    			pattern = /<B>/g;
    			str = str.replace(pattern, "<strong>");
    			pattern = //g;
    			str = str.replace(pattern, "</strong>");
    			pattern = //g;
    			str = str.replace(pattern, "");
    			pattern = //g;
    			str = str.replace(pattern, "");
    			pattern= //g;
    			str = str.replace(pattern, "");
                pattern= //g;
                str = str.replace(pattern, "");
                pattern= //g;
                str = str.replace(pattern, "");
                pattern = /LEFT/g;
                str = str.replace(pattern, "left");
                pattern = /RIGHT/g;
                str = str.replace(pattern, "right");
                pattern = /JUSTIFY/g;
                   str = str.replace(pattern, "justify");
                pattern = /&lt;p/g;
                str = str.replace(pattern, "&lt;span ");
                pattern = //g;
                str = str.replace(pattern, "");
                pattern = /&lt;P/g;
                str = str.replace(pattern, "&lt;span ");
                pattern = //g;
                str = str.replace(pattern, "");
                pattern = //g;
                str = str.replace(pattern, "");
                return str;
    		}
    
  18. anyone know how to replace or reformat the img tag tried this

    pattern = /<IMG/gi;
    str = str.replace(pattern, “/gi;
    str = str.replace(pattern, “src=$1/>”);

    Thanks

  19. Pingback: Igor Costa » Blog Archive » #6 Flex Hack - RichTextEditor to output XHTML 1.1 valid

  20. thanks guys! I had/have a problem with bullets not appearing with (any) embedded font in a Flex app. I took this code & added:

    pattern = //gi;
    str = str.replace(pattern, “”);

    as a (nasty) workaround.

    Damn handy being able to style RichTextEditor output with css too.

    Cheers!

  21. In case you prefer to convert the HTML only at time of publish (in an application server), here’s Matthew’s code ported in Java – that should save you the 5 minutes it took me to do it ;-) :

        public static String convertFlashToXHtml(String str)
        {
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("COLOR=\"(.*?)\"", "color:$1;");
                str = str.replaceAll("SIZE=\"(.*?)\"", "font-size:$1px;");
                str = str.replaceAll("FACE=\"(.*?)\"", "font-family:$1;");
                str = str.replaceAll("ALIGN=\"(.*?)\"", "text-align:$1;");
                str = str.replaceAll("LETTERSPACING=\".*?\"", "");
                str = str.replaceAll("KERNING=\".*?\"", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("", "");
                str = str.replaceAll("<I>", "<em>");
                str = str.replaceAll("</I>", "</em>");
                str = str.replaceAll("<B>", "<strong>");
                str = str.replaceAll("</B>", "</strong>");
                str = str.replaceAll("", "");
                return str.replaceAll("", "");
        }
    
  22. Damn!! Didn’t see the formatting tags. Hope this is the good one:

    /** Convert a flex/flash html string to the official html standard, removing custom flex tags. */
    	function convertFlexHtmlToStandard($string){
    
    		// Replace all textformat starting tags. Note that we replace "" by ""
    		$result = ereg_replace("]*&gt;", "", $string);
    
    		// Replace all ending textformat ending tags
    		$result = ereg_replace("", "", $result);
    
    		// Replace all size="XXXX" by the style='XXXXpx' expression
    		$result = ereg_replace('SIZE="([^"]*)"', "style='font-size:\\1px;'", $result);
    
    		return $result;
    
    	}
    
    • @James,

      Thanks for the contribution, this is by far my most commented post, I deleted the bad formatted version. I have to make those formatting comments more noticeable one day :) .

  23. Pingback: Flex Tips - Obtenir un texte HTML valide ? partir du RichTextEditor (htmlText) - Adobe Flex Tutorial - Tutoriaux Flex Builder, MXML, ActionScript, AS3

  24. I’m trying to insert a block of code into this manually to test it and the lack of escape characters is, of course, throwing an error. The problem is, my whole use for this script you guys have written (thank you a million times by the way) will be to insert escape characters before any and all single and double quotation marks. Quite the paradoxical quandry that I am having trouble finding my way out of.

    The purpose is to add the escape charaters, then send the edited string to a php file, which would throw an error without the escape characters. Any thoughts?

  25. Pingback: Using Adobe Flex RichTextEditor for CMS « Zero Credibility

  26. Pingback: Fixing HTML from Adobe Flex’s RichTextEditor « Zero Credibility

  27. Pingback: Using Adobe Flex RichTextEditor for CMS « Keith Collins

  28. Pingback: Tweets that mention Flex: Export valid HTML from the RichTextEditor -- Topsy.com

  29. It has a nice work from another nice expert who has done a great work!

    http://blog.flashweb.org/archives/7

    package flex.common
    {
    	import flash.xml.XMLDocument;
    	import flash.xml.XMLNode;
    
    	public class RteHtmlParser
    	{
    		public var SET_P:String = 'DIV';
    		public var SET_LI:String = 'LI';
    		public var SET_FONT:String = 'SPAN';
    
    		public var SET_UL:String = 'UL';
    		public var SET_BR:String = 'BR';
    
    		public var ignoreParagraphSpace:Boolean = false;
    
    		private var out_xml:XML;
    
    		public function RteHtmlParser()
    		{
    		}
    
    		// not those line breaks that kills the SQL
    		public function get StringFormat():String
    		{
    			if (!out_xml) return '';
    
    			XML.prettyIndent = 0;
    			// remove the /n from the string
    			// we want a string out!
    			var s:String = unescape(unescape(escape(out_xml.children()).split('%0A').join('')));
    			XML.prettyIndent = 2;
    
    			return s;
    		}
    
    		// nice looking string
    		public function get XMLFormat():String
    		{
    			if (!out_xml) return '';
    			return unescape(out_xml.children().toXMLString());
    		}
    
    		// the xml
    		public function get XMLObject():XML
    		{
    			return out_xml;
    		}
    
    
    		//________________________________________________________________________________________________________
    		//                                                                                             HTML PARSER
    
    		public function ParseToHTML(string:String):void
    		{
    			var xml_doc:XMLDocument = new XMLDocument(""+string+"");
    			var nxml:XMLNode = (ignoreParagraphSpace) ? xml_doc.firstChild : manage_space(xml_doc.firstChild);
    
    			var xml:XML = XML(nxml.toString());
    			var t1:XML;
    
    			// Remove all TEXTFORMAT
    			for( t1 = xml..TEXTFORMAT[0]; t1 != null; t1 = xml..TEXTFORMAT[0] ) {
    				t1.parent().replace( t1.childIndex(), t1.children() );
    			}
    
    			//add br tag
    			if (SET_BR)
    				xml = add_br_tag(xml);
    
    			// add ul tag
    			xml = add_ul_tag(xml);
    
    			// format css
    			xml = add_css(xml);
    
    			// format new names
    			xml = set_new_name(xml);
    
    			out_xml = xml;
    		}
    
    		private function add_ul_tag(xml:XML):XML
    		{
    			var t1:XML;
    			var t2:XML = new XML();
    			var el:XMLList = xml.children();
    			var ul:XML;
    
    			for each (t1 in el) {
    				if (t1.name().localName != 'LI') {
    					t2.appendChild(t1.copy());
    
    				} else if (t1.childIndex() == 0) {
    					ul = new XML();
    					ul.appendChild(t1.copy());
    					t2.appendChild(ul);
    
    				} else if (el[t1.childIndex()-1].name().localName != 'LI') {
    					ul = new XML();
    					ul.appendChild(t1.copy());
    					t2.appendChild(ul);
    
    				} else {
    					ul.appendChild(t1.copy());
    
    				}
    			}
    
    			return t2;
    		}
    
    		private function add_br_tag(xml:XML):XML
    		{
    			var br:XML;
    
    			for each (var i:XML in xml.children()) {
    				if (!has_text(i)) {
    					br = copy_attributes(i.descendants('FONT')[0], new XML());
    					i.parent().replace(i.childIndex(), br);
    				}
    			}
    			return xml;
    		}
    
    		private function set_new_name(xml:XML):XML
    		{
    			var t1:XML;
    			// set new P
    			if (SET_P == null)
    			{
    				for( t1 = xml..P[0]; t1 != null; t1 = xml..P[0] ) {
    					t1.parent().replace(t1.childIndex(), t1.children());
    				}
    			}
    			else if (SET_P.toLocaleUpperCase() != 'P') {
    				for( t1 = xml..P[0]; t1 != null; t1 = xml..P[0] ) {
    					t1.setName(SET_P);
    				}
    			}
    			// set new UL
    			if (SET_UL == null)
    			{
    				for( t1 = xml..UL[0]; t1 != null; t1 = xml..UL[0] ) {
    					t1.parent().replace(t1.childIndex(), t1.children());
    				}
    			}
    			else if (SET_UL.toLocaleUpperCase() != 'UL') {
    				for( t1 = xml..UL[0]; t1 != null; t1 = xml..UL[0] ) {
    					t1.setName(SET_FONT);
    				}
    			}
    			// set new LI
    			if (SET_LI == null)
    			{
    				for( t1 = xml..LI[0]; t1 != null; t1 = xml..LI[0] ) {
    					t1.parent().replace(t1.childIndex(), t1.children());
    				}
    			}
    			else if (SET_LI.toLocaleUpperCase() != 'LI') {
    				for( t1 = xml..LI[0]; t1 != null; t1 = xml..LI[0] ) {
    					t1.setName(SET_LI);
    				}
    			}
    			// set new FONT
    			if (SET_FONT == null)
    			{
    				for( t1 = xml..FONT[0]; t1 != null; t1 = xml..FONT[0] ) {
    					t1.parent().replace(t1.childIndex(), t1.children());
    				}
    			}
    			else if (SET_FONT.toLocaleUpperCase() != 'FONT') {
    				for( t1 = xml..FONT[0]; t1 != null; t1 = xml..FONT[0] ) {
    					t1.setName(SET_FONT);
    					// wierd browser rendering on e.g.
    					if (t1 == '') {
    						//t1.setChildren('');
    						//or you can just replace it with nothing
    						t1.parent().replace(t1.childIndex(), '');
    					}
    				}
    			}
    			// set new BR
    			if (SET_BR == null)
    			{
    				for( t1 = xml..BR[0]; t1 != null; t1 = xml..BR[0] ) {
    					t1.parent().replace(t1.childIndex(), t1.children());
    				}
    			}
    			else if (SET_BR.toLocaleUpperCase() != 'BR') {
    				for( t1 = xml..BR[0]; t1 != null; t1 = xml..BR[0] ) {
    					t1.setName(SET_BR);
    					// if it's closed like this  in html
    					// thebrowser might act wierd!
    					t1.setChildren('');
    				}
    			}
    			return xml;
    		}
    
    		private function add_css(xml:XML):XML
    		{
    			var t1:XML;
    			var t2:XML;
    			// Find all ALIGN
    			for each ( t1 in xml..@ALIGN ) {
    				t2 = t1.parent();
    				t2.@STYLE = "text-align:" + t1 + ";" + t2.@STYLE;
    				delete t2.@ALIGN;
    			}
    			// Find all FACE
    			for each ( t1 in xml..@FACE ) {
    				t2 = t1.parent();
    				t2.@STYLE = "font-family:'" + t1 + "';" + t2.@STYLE;
    				delete t2.@FACE;
    			}
    			// Find all SIZE
    			for each ( t1 in xml..@SIZE ) {
    				t2 = t1.parent();
    				t2.@STYLE = "font-size:" + t1 + "px;" + t2.@STYLE;
    				delete t2.@SIZE;
    			}
    			// Find all COLOR
    			for each ( t1 in xml..@COLOR ) {
    				t2 = t1.parent();
    				t2.@STYLE = "color:" + t1 + ";" + t2.@STYLE;
    				delete t2.@COLOR;
    			}
    			// Find all LETTERSPACING
    			for each ( t1 in xml..@LETTERSPACING ) {
    				t2 = t1.parent();
    				t2.@STYLE = "letter-spacing:" + t1 + "px;" + t2.@STYLE;
    				delete t2.@LETTERSPACING;
    			}
    			// Find all KERNING
    			for each ( t1 in xml..@KERNING ) {
    				t2 = t1.parent();
    				// ? css
    				delete t2.@KERNING;
    			}
    			return xml;
    		}
    
    		//________________________________________________________________________________________________________
    
    
    		//________________________________________________________________________________________________________
    		//                                                                                              RTE PARSER
    
    		public function ParseToRTE(string:String):void
    		{
    			var xml_doc:XMLDocument = new XMLDocument(""+string+"");
    			var nxml:XMLNode = (ignoreParagraphSpace) ? xml_doc.firstChild : manage_space(xml_doc.firstChild);
    
    			var xml:XML = new XML(nxml.toString());
    
    			// remove UL
    			xml = remove_ul_tag(xml);
    
    			// remove BR
    			xml = remove_br_tag(xml);
    
    			// format CSS
    			xml = remove_css(xml);
    
    			// format names
    			xml = rename_tags(xml);
    
    			//add TEXTFORMAT
    			xml = add_textformat(xml);
    
    			out_xml = xml;
    		}
    
    		private function remove_ul_tag(xml:XML):XML
    		{
    			var ul:XMLList = xml.elements(SET_UL);
    
    			for each (var i:XML in ul) {
    				i.parent().replace(i.childIndex(), i.children());
    			}
    
    			return xml;
    		}
    
    		private function remove_br_tag(xml:XML):XML
    		{
    			var br:XMLList = xml.descendants(SET_BR);
    			var p:XML;
    			var f:XML;
    
    			for each (var i:XML in br) {
    				p = new XML();
    				f = copy_attributes(i, new XML());
    				f.setChildren('');
    				p.appendChild(f);
    				i.parent().replace(i.childIndex(), p);
    			}
    
    			return xml;
    		}
    
    		private function remove_css(xml:XML):XML
    		{
    			var ar:Array;
    			var ta:Array;
    			var el:XML;
    			var name:String;
    
    			for each ( var i:XML in xml..@STYLE ) {
    				el = i.parent();
    				ar = String(el.@STYLE).split(';');
    
    				for (var j:uint = 0; j &lt; ar.length; j++) {
    					ta = ar[j].split(':');
    					name = ta[0].toLocaleLowerCase().split(' ').join('');
    
    					switch (name) {
    						case 'text-align':
    						el.@ALIGN = ta[1];
    						break;
    
    						case 'font-family':
    						el.@FACE = ta[1].split(&quot;'&quot;).join('').split('&quot;').join('');
    						break;
    
    						case 'font-size':
    						el.@SIZE = ta[1].split('px').join('');
    						break;
    
    						case 'color':
    						el.@COLOR = ta[1];
    						break;
    
    						case 'letter-spacing':
    						el.@LETTERSPACING = ta[1].split('px').join('');
    						break;
    					}
    				}
    
    				delete el.@STYLE;
    			}
    
    			return xml;
    		}
    
    		private function rename_tags(xml:XML):XML
    		{
    			var t:XML;
    			var el:XMLList;
    
    			// set new P
    			if (SET_P.toLocaleUpperCase() != 'P' &amp;&amp; SET_P != null) {
    				el = xml.descendants(SET_P);
    				for each (t in el) {
    					t.setName('P');
    				}
    			}
    			// set new LI
    			if (SET_LI.toLocaleUpperCase() != 'LI' &amp;&amp; SET_LI != null) {
    				el = xml.descendants(SET_LI);
    				for each (t in el) {
    					t.setName('LI');
    				}
    			}
    			// set new FONT
    			if (SET_FONT.toLocaleUpperCase() != 'FONT' &amp;&amp; SET_FONT != null) {
    				el = xml.descendants(SET_FONT);
    				for each (t in el) {
    					t.setName('FONT');
    				}
    			}
    			return xml;
    		}
    
    		private function add_textformat(xml:XML):XML
    		{
    			var m:XML = new XML();
    			var tf:XML;
    
    			for each (var i:XML in xml.children()) {
    				tf = new XML();
    				//tf.@LEADING = '2';
    				tf.appendChild(i.copy());
    				m.appendChild(tf);
    			}
    
    			return m;
    		}
    
    		//________________________________________________________________________________________________________
    
    
    
    		//________________________________________________________________________________________________________
    		//                                                                                              SOME TOOLS
    
    		private function has_text(xml:XML):Boolean
    		{
    			for each (var i:XML in xml.children()) {
    				if (i.nodeKind() == 'text') return true;
    				else if (has_text(i)) return true;
    			}
    
    			return false;
    		}
    
    		private function copy_attributes(x1:XML, x2:XML):XML
    		{
    			for each (var i:XML in x1.attributes()) {
    				x2.@[i.name().localName] = i;
    			}
    			return x2;
    		}
    
    		private function manage_space(node:XMLNode):XMLNode
    		{
    			for each (var n:XMLNode in node.childNodes)
    			{
    				if (n.nodeType == 3) n.nodeValue = n.nodeValue.split(' ').join('%20');
    				if (n.hasChildNodes()) manage_space(n);
    			}
    			return node;
    		}
    
    		//________________________________________________________________________________________________________
    	}
    }
    

    manpakhong@hotmail.com

  30. Pingback: Custom RichTextEditor | msn messenger smiley

  31. Pingback: Adobe Flex RichTextEditor Part 1 | Keith Collins

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s