$v) $val[$k] = self::raw2htmlname($v);
			return $val;
		} else {
			return preg_replace('/[^a-zA-Z0-9\-_:.]+/','', $val);
		}
	}
	
	/**
	 * Ensure that text is properly escaped for XML.
	 * 
	 * @see http://www.w3.org/TR/REC-xml/#dt-escape
	 * @param array|string $val String to escape, or array of strings
	 * @return array|string
	 */
	public static function raw2xml($val) {
		if(is_array($val)) {
			foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
			return $val;
		} else {
			return htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
		}
	}
	
	/**
	 * Ensure that text is properly escaped for Javascript.
	 *
	 * @param array|string $val String to escape, or array of strings
	 * @return array|string
	 */
	public static function raw2js($val) {
		if(is_array($val)) {
			foreach($val as $k => $v) $val[$k] = self::raw2js($v);
			return $val;
		} else {
			return str_replace(
				// Intercepts some characters such as <, >, and & which can interfere
				array("\\", '"', "\n", "\r", "'", "<", ">", "&"),
				array("\\\\", '\"', '\n', '\r', "\\'", "\\x3c", "\\x3e", "\\x26"),
				$val
			);
		}
	}
	/**
	 * Encode a value as a JSON encoded string.
	 *
	 * @param mixed $val Value to be encoded
	 * @return string JSON encoded string
	 */
	public static function raw2json($val) {
		return json_encode($val);
	}
	/**
	 * Encode an array as a JSON encoded string.
	 * THis is an alias to {@link raw2json()}
	 *
	 * @param array $val Array to convert
	 * @return string JSON encoded string
	 */
	public static function array2json($val) {
		return self::raw2json($val);
	}
	public static function raw2sql($val) {
		if(is_array($val)) {
			foreach($val as $k => $v) $val[$k] = self::raw2sql($v);
			return $val;
		} else {
			return DB::getConn()->addslashes($val);
		}
	}
	/**
	 * Convert XML to raw text.
	 * @uses html2raw()
	 * @todo Currently xx; entries are stripped; they should be converted
	 */
	public static function xml2raw($val) {
		if(is_array($val)) {
			foreach($val as $k => $v) $val[$k] = self::xml2raw($v);
			return $val;
		} else {
			// More complex text needs to use html2raw instead
			if(strpos($val,'<') !== false) return self::html2raw($val);
			else return html_entity_decode($val, ENT_QUOTES, 'UTF-8');
		}
	}
	/**
	 * Convert a JSON encoded string into an object.
	 *
	 * @param string $val
	 * @return object|boolean
	 */
	public static function json2obj($val) {
		return json_decode($val);
	}
	/**
	 * Convert a JSON string into an array.
	 * 
	 * @uses json2obj
	 * @param string $val JSON string to convert
	 * @return array|boolean
	 */
	public static function json2array($val) {
		return json_decode($val, true);
	}
	
	/**
	 * Converts an XML string to a PHP array
	 * See http://phpsecurity.readthedocs.org/en/latest/Injection-Attacks.html#xml-external-entity-injection
	 *
	 * @uses recursiveXMLToArray()
	 * @param string $val
	 * @param boolean $disableDoctypes Disables the use of DOCTYPE, and will trigger an error if encountered.
	 * false by default.
	 * @param boolean $disableExternals Disables the loading of external entities. false by default.
	 * @return array
	 */
	public static function xml2array($val, $disableDoctypes = false, $disableExternals = false) {
		// Check doctype
		if($disableDoctypes && preg_match('/\<\!DOCTYPE.+]\>/', $val)) {
			throw new InvalidArgumentException('XML Doctype parsing disabled');
		}
		// Disable external entity loading
		if($disableExternals) $oldVal = libxml_disable_entity_loader($disableExternals);
		try {
			$xml = new SimpleXMLElement($val);
			$result = self::recursiveXMLToArray($xml);
		} catch(Exception $ex) {
			if($disableExternals) libxml_disable_entity_loader($oldVal);
			throw $ex;
		}
		if($disableExternals) libxml_disable_entity_loader($oldVal);
		return $result;
	}
	/**
	 * Convert a XML string to a PHP array recursively. Do not 
	 * call this function directly, Please use {@link Convert::xml2array()}
	 * 
	 * @param SimpleXMLElement
	 * 
	 * @return mixed
	 */
	protected static function recursiveXMLToArray($xml) {
		if(is_object($xml) && get_class($xml) == 'SimpleXMLElement') {
			$attributes = $xml->attributes();
			foreach($attributes as $k => $v) {
				if($v) $a[$k] = (string) $v;
			}
			$x = $xml;
			$xml = get_object_vars($xml);
		}
		if(is_array($xml)) {
			if(count($xml) == 0) return (string) $x; // for CDATA
			foreach($xml as $key => $value) {
				$r[$key] = self::recursiveXMLToArray($value);
			}
			if(isset($a)) $r['@'] = $a; // Attributes
			return $r;
		}
		
		return (string) $xml;
	}
	
	/**
	 * Create a link if the string is a valid URL
	 *
	 * @param string The string to linkify
	 * @return A link to the URL if string is a URL
	 */
	public static function linkIfMatch($string) {
		if( preg_match( '/^[a-z+]+\:\/\/[a-zA-Z0-9$-_.+?&=!*\'()%]+$/', $string ) )
			return "$string";
		else
			return $string;
	}
	
	/**
	 * Simple conversion of HTML to plaintext.
	 * 
	 * @param $data string
	 * @param $preserveLinks boolean
	 * @param $wordwrap array 
	 */
	public static function html2raw($data, $preserveLinks = false, $wordWrap = 60, $config = null) {
		$defaultConfig = array(
			'PreserveLinks' => false,
			'ReplaceBoldAsterisk' => true,
			'CompressWhitespace' => true,
			'ReplaceImagesWithAlt' => true,
		);
		if(isset($config)) {
			$config = array_merge($defaultConfig,$config);
		} else {
			$config = $defaultConfig;
		}
		$data = preg_replace("/