//=================================================================================================
var
	ntElement   = 1, 
	ntAttribute = 2, 
	ntText      = 3, 
	ntCData     = 4, 
	ntComment   = 8, 
	ntDocument  = 9;
//=================================================================================================
var
	charCodes = 
		[
			160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 
			178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 
			196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 
			214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 
			232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 
			250, 251, 252, 253, 254, 255, 338, 339, 352, 353, 376, 402, 710, 732, 8211, 8212, 8216, 
			8217, 8218, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8249, 8250, 8364, 8482 
		], 
	specialChar = 
		[
			"&nbsp;", "&iexcl;", "&cent;", "&pound;", "&curren;", "&yen;", "&brvbar;", "&sect;", 
			"&uml;", "&copy;", "&ordf;", "&laquo;", "&not;", "&shy;", "&reg;", "&macr;", "&deg;", 
			"&plusmn;", "&sup2;", "&sup3;", "&acute;", "&micro;", "&para;", "&middot;", "&cedil;", 
			"&sup1;", "&ordm;", "&raquo;", "&frac14;", "&frac12;", "&frac34;", "&iquest;", 
			"&Agrave;", "&Aacute;", "&Acirc;", "&Atilde;", "&Auml;", "&Aring;", "&AElig;", 
			"&Ccedil;", "&Egrave;", "&Eacute;", "&Ecirc;", "&Euml;", "&Igrave;", "&Iacute;", 
			"&Icirc;", "&Iuml;", "&ETH;", "&Ntilde;", "&Ograve;", "&Oacute;", "&Ocirc;", "&Otilde;", 
			"&Ouml;", "&times;", "&Oslash;", "&Ugrave;", "&Uacute;", "&Ucirc;", "&Uuml;", "&Yacute;", 
			"&THORN;", "&szlig;", "&agrave;", "&aacute;", "&acirc;", "&atilde;", "&auml;", "&aring;", 
			"&aelig;", "&ccedil;", "&egrave;", "&eacute;", "&ecirc;", "&euml;", "&igrave;", 
			"&iacute;", "&icirc;", "&iuml;", "&eth;", "&ntilde;", "&ograve;", "&oacute;", "&ocirc;", 
			"&otilde;", "&ouml;", "&divide;", "&oslash;", "&ugrave;", "&uacute;", "&ucirc;", 
			"&uuml;", "&yacute;", "&thorn;", "&yuml;"
		];
//-------------------------------------------------------------------------------------------------
	specialChar[178]  = "&OElig;";
	specialChar[179]  = "&oelig;";
	specialChar[192]  = "&Scaron;";
	specialChar[193]  = "&scaron;";
	specialChar[216]  = "&Yuml;";
	specialChar[242]  = "&fnof;";
	specialChar[550]  = "&circ;";
	specialChar[572]  = "&tilde;";
	specialChar[8051] = "&ndash;";
	specialChar[8052] = "&mdash;";
	specialChar[8056] = "&lsquo;";
	specialChar[8057] = "&rsquo;";
	specialChar[8058] = "&sbquo;";
	specialChar[8060] = "&ldquo;";
	specialChar[8061] = "&rdquo;";
	specialChar[8062] = "&bdquo;";
	specialChar[8064] = "&dagger;";
	specialChar[8065] = "&Dagger;";
	specialChar[8066] = "&bull;";
	specialChar[8070] = "&hellip;";
	specialChar[8080] = "&permil;";
	specialChar[8089] = "&lsaquo;";
	specialChar[8090] = "&rsaquo;";
	specialChar[8204] = "&euro;";
	specialChar[8322] = "&trade;";
//-------------------------------------------------------------------------------------------------
function toXml( value, type )
{
	if ( typeof( type ) != "undefined")
	{
		switch ( type )
		{
			case dtBoolean:
				if ( value )
					return "1";
				else
					return "0";
				
				break;
			case dtDateTime:
				return value.formatString("s");
				break;
			case dtDouble:
			case dtMoney:
			case dtPercentage:
				return value.formatString("0.0#########").replace(",", ".");
				break;
			case dtInteger:
			case dtLong:
				break;
			case dtString:
			case dtGuid:
				value = value.replace( /\&/gi, "&amp;");
				value = value.replace( /\"/gi, "&quot;");
				value = value.replace( /\</gi, "&lt;");
				value = value.replace( /\>/gi, "&gt;");
				
				break;
			default:
				throw new Error("Illegal assignment to parameter \"type\" (" + type + ").");
		}
	}
	else
	{
		// TODO: bep welk type...
	}
	
	return value;
}
//=================================================================================================
function fromXml( value, type )
{
	if ( typeof( value ) != "undefined" && typeof( value.firstChild ) != "undefined")
		value = value.firstChild ? value.firstChild.data : null;
	
	if ( value == null || String( value ) == "")
		return null;
	
	switch ( type )
	{
		case dtBoolean:
			if ( String( value ) == "0" || String( value ).toLowerCase() == "false" || String( value ).toLowerCase() == "no")
				return false;
			else
				return true;
			
			break;
		case dtDateTime:
			value = parseXmlDate( value );
			
			if ( isNaN( value ) )
				return null;
			else
				return value;
			
			break;
		case dtDouble:
		case dtMoney:
		case dtPercentage:
			value = parseFloat( value );
			
			if ( isNaN( value ) )
				return null;
			else
				return value;
			
			break;
		case dtInteger:
		case dtLong:
			value = parseInt( value );
			
			if ( isNaN( value ) )
				return null;
			else
				return value;
			
			break;
		case dtString:
		case dtGuid:
			value = value.replace( /&amp;/gi,  "&");
			value = value.replace( /&quot;/gi, "\"");
			value = value.replace( /&lt;/gi,   "<");
			value = value.replace( /&gt;/gi,   ">");
			
			return value;
			break;
		default:
			throw new Error("Illegal assignment to parameter \"type\" (" + type + ").");
	}
}
//=================================================================================================
function parseXmlDate( value )
{
	var
		regex = /^(\d{4}-\d{2}-\d{2})(T\d{2}:\d{2}:\d{2}(\.\d{1,7})?)?$/i;
	
	if ( regex.test( value ) )
	{
		var
			date = value.split( /[-T:\.]/g );
		
		for ( var i = 0; i < date.length; i++ )
			while ( date[i].startsWith("0") && String( date[i] ).length > 1 )
				date[i] = date[i].substr( 1 );
			
		var
			year   = parseInt( date[0] );
			month  = parseInt( date[1] );
			day    = parseInt( date[2] );
			hour   = parseInt( date[3] );
			minute = parseInt( date[4] );
			second = parseInt( date[5] );
		
		if ( isNaN( hour ) ) 
			hour = 0;
		
		if ( isNaN( minute ) ) 
			minute = 0;
		
		if ( isNaN( second ) ) 
			second = 0;
		
		return new Date( year, month - 1, day, hour, minute, second );
	}
	else
		return parseInt("knaag");
}
//=================================================================================================
function htmlEncode( HTML )
{
	var
		retVal;
	
	try
	{
		retVal = new String( HTML );
		retVal = retVal.replace( /&/g, "&amp;");
		
		for ( var i = 0; i < charCodes.length; i++ )
		{
			var
				code = charCodes[i], 
				html = specialChar[code - 160];
			
			retVal = retVal.replace( new RegExp( String.fromCharCode( code ), "g"), "&amp;" + html.substr( 1 ) );
		}
		
		retVal = retVal.replace( /</g, "&lt;");
		retVal = retVal.replace( />/g, "&gt;");
		retVal = retVal.replace( /"/g, "&quot;");	//"
	}
	catch ( error )
	{
		try
		{
			retVal = HTML.join(", ");
		}
		catch ( error )
		{
			retVal = HTML;
		}
	}
	
	return retVal;
}
//=================================================================================================
function showXml( node, name )
{
	if ( typeof( name ) == "undefined" || name == null )
		name = "";
	
	if ( typeof( node ) != "object" || typeof( node.childNodes ) == "undefined")
		throw new Error("Illegal argument. First argument is not an XmlNode.");
	
	if ( typeof( node.documentElement ) != "undefined")
		node = node.documentElement;
	
	var
		bytes = String("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n").length, 
		win   = window.open("", "frmXML" + name, "toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,width=788,height=570");
	
	if ( typeof( Xml ) != "undefined" && typeof( Xml.toString ) == "function")
		bytes += Xml.toString( node ).length;
	
	if ( win )
	{
		win.document.open();
		win.document.writeln("<html><head><title>Xml " + name + "</title></head><body style=\"font-family: Lucida Console, Courier New; font-size:11px; color:navy; margin:5px; background-color:white;\">&lt;?xml version=\"1.0\" encoding=\"Windows-1252\"?&gt;");
		win.document.writeln( buildXml( node ) );
		
		if ( typeof( Xml ) != "undefined" && typeof( Xml.toString ) == "function")
		{
			if ( bytes < 2048 ) 
				win.document.writeln("<div style=\"clear:both; margin-top:10px; font-family:Verdana; color:black;\"><b>XML size:</b> " + bytes + " bytes</div></html>");
			else if ( bytes / 1024 < 2048 ) 
				win.document.writeln("<div style=\"clear:both; margin-top:10px; font-family:Verdana; color:black;\"><b>XML size:</b> " + (Math.round(bytes / 1024 * 100) / 100) + " kB</div></html>");
			else if ( bytes / 1024 / 1024 < 2048 ) 
				win.document.writeln("<div style=\"clear:both; margin-top:10px; font-family:Verdana; color:black;\"><b>XML size:</b> " + (Math.round(bytes / 1024 / 1024 * 100) / 100) + " MB</div></html>");
		}
		
		win.document.writeln("</body></html>");
		win.document.close();
		
		win.focus();
	}
}
//=================================================================================================
function nodeName( node )
{
	var
		retVal = node.nodeName;
	
	if ( node.attributes )
	{
		for ( var i = 0; i < node.attributes.length; i++ )
		{
			var
				attr = node.attributes.item( i );
			
			if ( attr.nodeName != "xmlns:sql" && attr.value != "null" && attr.value != "" && attr.value != null )
				retVal += " " + attr.nodeName + "=<font color=\"blue\">\"" + attr.value.replace(/\"/g, "&amp;quot;") + "\"</font>";
		}
	}
		
	return retVal;
}
//=================================================================================================
function buildXml( node, tabs )
{
	var
		retVal = "";
	
	if ( tabs == undefined )
		tabs = "";
	
	if ( node.childNodes.length ) 
	{
		retVal += "<br/>" + tabs + "&lt;" + nodeName( node ) + "&gt;";
		
		for ( var i = 0; i < node.childNodes.length; i++ )
			retVal += buildXml( node.childNodes[i], tabs + "&nbsp;&nbsp;&nbsp;");
		
		var
			length = node.childNodes.length;
		
		for ( var i = 0; i < node.childNodes.length; i++ )
			if ( node.childNodes[i].nodeType == ntText || node.childNodes[i].nodeType == ntCData )
				length--;
		
		if ( length > 0 )
			retVal += "<br/>" + tabs;
		
		retVal += "&lt;/" + node.nodeName + "&gt;";
	}
	else if ( node.nodeType == ntText )
	{
		var
			text = null;
		
		if ( typeof( node.value ) != "undefined")
			text = node.value;
		else if ( typeof( node.text ) != "undefined")
			text = node.text;
		else if ( typeof( node.nodeValue ) != "undefined")
			text = node.nodeValue;
		
		if ( typeof( text ) != "undefined" && text != "" && text != null )
			retVal += "<font color=\"black\"><b>" + toXml( text, dtString ).htmlEncode().replace(/[\r\n]/gi, "<br/>") + "</b></font>";
	}
	else if ( node.nodeType == ntCData )
	{
		var
			text = null;
		
		if ( typeof( node.value ) != "undefined")
			text = node.value;
		else if ( typeof( node.text ) != "undefined")
			text = node.text;
		else if ( typeof( node.nodeValue ) != "undefined")
			text = node.nodeValue;
		
		retVal += "<font color=\"red\">&lt;![CDATA[<br/><div style=\"margin-left:" + (tabs.length / 6) * 7 + "px; padding-left:3px; border-left:1px solid #C00000;\"><font color=\"black\">";
		retVal += toXml( text, dtString ).replace(/[\r\n]/gi, "<br/>").replace(/[\t]/gi, "&nbsp;&nbsp;&nbsp;");
		retVal += "</font><br/></div>" + tabs + "]]&gt;</font>";
	}
	else if ( node.nodeType == ntElement )
		retVal += "<br/>" + tabs + "&lt;" + nodeName( node ) + "/&gt;";
	
	return retVal;
}
//=================================================================================================
