var prev_line_req = '|div|p|table|tbody|tr|td|th|title|head|body|script|comment|li|meta|h1|h2|h3|h4|h5|h6|hr|ul|ol|option|';
var next_line_req = '|html|head|body|p|th|style|';

var req_remark = new RegExp();
req_remark.compile("^<!--(.*)-->$");

var hypen_req = new RegExp();
hypen_req.compile("-$");
function receive_xhtml(node, lang, encoding, need_nl, inside_pre) {
	var i;
	var txt = '';
	var inherit = node.childNodes;
	var inherit_length = inherit.length;
	var hold_tag;
	var prnt_line = need_nl ? true : false;
	var page_mode = true;
	
	for (i = 0; i < inherit_length; i++) {
		var inh = inherit[i];
		
		switch (inh.nodeType) {
			case 1: {
				var hold_tag = String(inh.tagName).toLowerCase();
				
				if (hold_tag == '') break;
				
				if (hold_tag == 'meta') {
					var meta_name = String(inh.name).toLowerCase();
					if (meta_name == 'generator') break;
				}
				
				if (!need_nl && hold_tag == 'body') { 
					page_mode = false;
				}
				
				if (hold_tag == '!') { 
					var splts = req_remark.exec(inh.text);
					
					if (splts) {
						var inerTxt = splts[1];
						txt += set_comm(inerTxt);
					}
				} else {
					if (hold_tag == 'html') {
						txt = '<?xml version="1.0" encoding="'+encoding+'"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n';
					}
					
					if (prev_line_req.indexOf('|'+hold_tag+'|') != -1) {
						if ((prnt_line || txt != '') && !inside_pre) txt += '\n';
					} else {
						prnt_line = true;
					}
					
					txt += '<'+hold_tag;
					
					var xprop = inh.attributes;
					var xprop_length = xprop.length;
					var xprop_value;
					
					var xprop_lang = false;
					var xprop_xml_lang = false;
					var xprop_xmlns = false;
					
					var is_alt_xprop = false;
					
					for (j = 0; j < xprop_length; j++) {
						var xprop_name = xprop[j].nodeName.toLowerCase();
						
						if (!xprop[j].specified && 
							(xprop_name != 'selected' || !inh.selected) && 
							(xprop_name != 'style' || inh.style.cssText == '') && 
							xprop_name != 'value') continue; 
						
						if (xprop_name == '_moz_dirty' || 
							xprop_name == '_moz_resizing' || 
							hold_tag == 'br' && 
							xprop_name == 'type' && 
							inh.getAttribute('type') == '_moz') continue;
						
						var chk_vald_xprop = true;
						
						switch (xprop_name) {
							case "style":
								xprop_value = inh.style.cssText;
								break;
							case "class":
								xprop_value = inh.className;
								break;
							case "http-equiv":
								xprop_value = inh.httpEquiv;
								break;
							case "noshade": break; 
							case "checked": break;
							case "selected": break;
							case "multiple": break;
							case "nowrap": break;
							case "disabled": break;
								xprop_value = xprop_name;
								break;
							default:
								try {
									xprop_value = inh.getAttribute(xprop_name, 2);
								} catch (e) {
									chk_vald_xprop = false;
								}
								break;
						}
						
						if (xprop_name == 'lang') {
							xprop_lang = true;
							xprop_value = lang;
						}
						if (xprop_name == 'xml:lang') {
							xprop_xml_lang = true;
							xprop_value = lang;
						}
						if (xprop_name == 'xmlns') xprop_xmlns = true;
						if (chk_vald_xprop) {
							if (!(hold_tag == 'li' && xprop_name == 'value')) {
								txt += ' '+xprop_name+'="'+setAttr(xprop_value)+'"';
							}
						}
						
						if (xprop_name == 'alt') is_alt_xprop = true;
					}
					
					if (hold_tag == 'img' && !is_alt_xprop) {
						txt += ' alt=""';
					}
					
					if (hold_tag == 'html') {
						if (!xprop_lang) txt += ' lang="'+lang+'"';
						if (!xprop_xml_lang) txt += ' xml:lang="'+lang+'"';
						if (!xprop_xmlns) txt += ' xmlns="http://www.w3.org/1999/xhtml"';
					}
					
					if (inh.canHaveChildren || inh.hasChildNodes()){
						txt += '>';
						txt += receive_xhtml(inh, lang, encoding, true, inside_pre || hold_tag == 'pre' ? true : false);
						txt += '</'+hold_tag+'>';
					} else {
						if (hold_tag == 'style' || hold_tag == 'title' || hold_tag == 'script') {
							txt += '>';
							var inerTxt;
							if (hold_tag == 'script') {
								inerTxt = inh.text;
							} else {
								inerTxt = inh.innerHTML;
							}
							
							if (hold_tag == 'style') {
								inerTxt = String(inerTxt).replace(/[\n]+/g,'\n');
							}
							
							txt += inerTxt+'</'+hold_tag+'>';
						} else {
							txt += ' />';
						}
					}
				}
				break;
			}
			case 3: {
				if (!inside_pre) {
					if (inh.nodeValue != '\n') {
						txt += setTxt(inh.nodeValue);
					}
				} else {
					txt += inh.nodeValue;
				}
				break;
			}
			case 8: { 
				txt += set_comm(inh.nodeValue);
				break;
			}
			default:
				break;
		}
	}
	
	if (!need_nl && !page_mode) { 
		txt = txt.replace(/<\/?head>[\n]*/gi, "");
		txt = txt.replace(/<head \/>[\n]*/gi, "");
		txt = txt.replace(/<\/?body>[\n]*/gi, "");
	}
	
	return txt;
}

function set_comm(txt) {
	txt = txt.replace(/--/g, "__");
	
	if(hypen_req.exec(txt)) {
		txt += " ";
	}
	
	return "<!--"+txt+"-->";
}

function setTxt(txt) {
	return String(txt).replace(/\n{2,}/g, "\n").replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\u00A0/g, "&nbsp;");
}
function setAttr(txt) {
	return String(txt).replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;");
}
