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

57 Comments

  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. Would like to vote this being one of the most usefull posts of the year….ok..well maybe the month.

    Good work.

  10. 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;
                   }
    

  11. 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

  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. 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?

  16. I checked the posts, there was some missing information. The posts all seem to be intact now, thanks for letting me know of the issue.

  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. sorry

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

  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;
    
    	}
    

    1. @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. 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?

  24. […] Fixing HTML from Adobe Flex’s RichTextEditor September 17, 2008 Leave a comment Go to comments After my last post regarding using the RichTextEditor for CMS, I realized the extent to which the HTML coming out of the RTE sucked ass. Again, based on the awful and obsolete HTML provided by the RTE, I honestly can’t imagine what Adobe was thinking. What good can this thing be used for? An example of what it spits out from Thanks Mister: […]

  25. 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

Comments are closed.