Index: /CKEditor/branches/prototype/_source/core/htmlparser.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/htmlparser.js	(revision 2916)
+++ /CKEditor/branches/prototype/_source/core/htmlparser.js	(revision 2917)
@@ -33,5 +33,5 @@
 (function()
 {
-	var attribsRegex	= /([\w:]+)(?:=(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))?/g,
+	var attribsRegex	= /([\w:]+)\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+))?/g,
 		emptyAttribs	= {checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};
 
@@ -155,5 +155,5 @@
 						{
 							var attName = attribMatch[1].toLowerCase(),
-								attValue = attribMatch[2] || attribMatch[3] || attribMatch[4];
+								attValue = attribMatch[2] || attribMatch[3] || attribMatch[4] || '';
 
 							if ( !attValue && emptyAttribs[ attName ] )
Index: /CKEditor/branches/prototype/_source/core/htmlparser/element.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/htmlparser/element.js	(revision 2916)
+++ /CKEditor/branches/prototype/_source/core/htmlparser/element.js	(revision 2917)
@@ -55,9 +55,11 @@
 		isEmpty		= !!dtd.$empty[ name ];
 
+	this.isEmpty	= isEmpty;
+	this.isUnknown	= !dtd[ name ];
+
 	/** @private */
 	this._ =
 	{
 		isBlockLike : isBlockLike,
-		isEmpty : isEmpty,
 		hasInlineStarted : isEmpty || !isBlockLike
 	};
@@ -131,7 +133,7 @@
 
 			// Close the tag.
-			writer.openTagClose( this.name, this._.isEmpty );
+			writer.openTagClose( this.name, this.isEmpty );
 
-			if ( !this._.isEmpty )
+			if ( !this.isEmpty )
 			{
 				// Send children.
Index: /CKEditor/branches/prototype/_source/core/htmlparser/fragment.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/htmlparser/fragment.js	(revision 2916)
+++ /CKEditor/branches/prototype/_source/core/htmlparser/fragment.js	(revision 2917)
@@ -86,5 +86,5 @@
 						currentDtd = currentNode.name && CKEDITOR.dtd[ currentNode.name ];
 
-					if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] ) )
+					if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] || !CKEDITOR.dtd[ newTagName ] ) )
 					{
 						// Get a clone for the pending element.
@@ -105,7 +105,12 @@
 		};
 
-		parser.onTagOpen = function( tagName, attributes )
+		parser.onTagOpen = function( tagName, attributes, selfClosing )
 		{
 			var element = new CKEDITOR.htmlParser.element( tagName, attributes );
+
+			// "isEmpty" will be always "false" for unknown elements, so we
+			// must force it if the parser has identified it as a selfClosing tag.
+			if ( element.isUnknown && selfClosing )
+				element.isEmpty = true;
 
 			// This is a tag to be removed if empty, so do not add it immediately.
@@ -120,5 +125,5 @@
 
 			// If the element cannot be child of the current element.
-			if ( !currentDtd[ tagName ] )
+			if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )
 			{
 				// If this is the fragment node, just ignore this tag and add
@@ -130,5 +135,5 @@
 
 				// If the element name is the same as the current element name,
-				// then just close the current one an append the new one to the
+				// then just close the current one and append the new one to the
 				// parent. This situation usually happens with <p>, <li>, <dt> and
 				// <dd>, specially in IE.
@@ -164,5 +169,5 @@
 			currentNode.add( element );
 
-			if ( !element._.isEmpty )
+			if ( !element.isEmpty )
 				currentNode = element;
 		};
@@ -194,5 +199,5 @@
 			{
 				// If we didn't find any parent to be closed, let's check the
-				// peding list.
+				// pending list.
 				for ( ; index < pendingInline.length ; index++ )
 				{
Index: /CKEditor/branches/prototype/_source/plugins/htmldataprocessor/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/htmldataprocessor/plugin.js	(revision 2916)
+++ /CKEditor/branches/prototype/_source/plugins/htmldataprocessor/plugin.js	(revision 2917)
@@ -26,26 +26,31 @@
 	init : function( editor, pluginPath )
 	{
-		editor.dataProcessor =
-		{
-			toHtml : function( data )
-			{
-				// The source data is already HTML, so just return it as is.
-				return data;
-			},
-
-			toDataFormat : function( element )
-			{
-				var writer = this.writer,
-					fragment = CKEDITOR.htmlParser.fragment.fromHtml( element.getHtml() );
-
-				writer.reset();
-
-				fragment.writeHtml( writer );
-
-				return writer.getHtml( true );
-			},
-
-			writer : new CKEDITOR.htmlWriter()
-		};
+		editor.dataProcessor = new CKEDITOR.htmlDataProcessor();
 	}
 });
+
+CKEDITOR.htmlDataProcessor = function()
+{
+	this.writer = new CKEDITOR.htmlWriter();
+};
+
+CKEDITOR.htmlDataProcessor.prototype =
+{
+	toHtml : function( data )
+	{
+		// The source data is already HTML, so just return it as is.
+		return data;
+	},
+
+	toDataFormat : function( element )
+	{
+		var writer = this.writer,
+			fragment = CKEDITOR.htmlParser.fragment.fromHtml( element.getHtml() );
+
+		writer.reset();
+
+		fragment.writeHtml( writer );
+
+		return writer.getHtml( true );
+	}
+};
Index: /CKEditor/branches/prototype/_source/tests/core/htmlparser/fragment.html
===================================================================
--- /CKEditor/branches/prototype/_source/tests/core/htmlparser/fragment.html	(revision 2917)
+++ /CKEditor/branches/prototype/_source/tests/core/htmlparser/fragment.html	(revision 2917)
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>CKEDITOR.htmlParser.fragment</title>
+	<link rel="stylesheet" type="text/css" href="../../test.css" />
+	<script type="text/javascript" src="../../../../ckeditor_source.js"></script>
+	<script type="text/javascript" src="../../test.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+CKEDITOR.test.addTestCase( (function()
+{
+	// Local reference to the "assert" object.
+	var assert = CKEDITOR.test.assert;
+
+	return {
+		test_fromHtml_1 : function()
+		{
+			var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<p>Test</p>' );
+
+			assert.areSame( 1, fragment.children.length, 'Wrong size' );
+			assert.areSame( CKEDITOR.NODE_ELEMENT, fragment.children[0].type, 'Wrong child type' );
+			assert.areSame( 'p', fragment.children[0].name, 'Wrong child name' );
+		},
+
+		name : document.title
+	};
+})() );
+
+	//]]>
+	</script>
+</head>
+<body>
+</body>
+</html>
Index: /CKEditor/branches/prototype/_source/tests/plugins/htmldataprocessor/htmldataprocessor.html
===================================================================
--- /CKEditor/branches/prototype/_source/tests/plugins/htmldataprocessor/htmldataprocessor.html	(revision 2917)
+++ /CKEditor/branches/prototype/_source/tests/plugins/htmldataprocessor/htmldataprocessor.html	(revision 2917)
@@ -0,0 +1,102 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Plugin: htmldataprocessor</title>
+	<link rel="stylesheet" type="text/css" href="../../test.css" />
+	<script type="text/javascript" src="../../../../ckeditor_source.js"></script>
+	<script type="text/javascript" src="../../test.js"></script>
+	<script type="text/javascript">
+
+CKEDITOR.plugins.load( 'htmldataprocessor' );
+
+	</script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+var testCase;
+
+CKEDITOR.test.addTestCase( testCase = (function()
+{
+	// Local references.
+	var assert = CKEDITOR.test.assert;
+
+	// In these tests, we may "reset" the writer rules to avoid it formatting
+	// the output, making the assertion easier to the done. We don't need to
+	// test formatting features here, so this is ok.
+	var getDataProcessor = function()
+	{
+		var dataProcessor = new CKEDITOR.htmlDataProcessor();
+		dataProcessor.writer._.rules = [];
+		return dataProcessor;
+	};
+	
+	// These tests go far beyond the strict htmlDataProcessor code testing. We
+	// are actually testing the entire parsing system here. The combination of
+	// htmlParser and htmlWriter inside htmlDataProcessor is useful in this
+	// sense.
+
+	return {
+		test_toDataFormat_1a : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><p>Test</p></div>' );
+
+			assert.areSame( '<p>Test</p>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		test_toDataFormat_1b : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><x:x>Test</x:x></div>' );
+
+			// IE adds the XML namespace tag.
+			if ( CKEDITOR.env.ie )
+				assert.areSame( '<?xml:namespace prefix="x" /><x:x>Test</x:x>', getDataProcessor().toDataFormat( element ) );
+			else
+				assert.areSame( '<x:x>Test</x:x>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		test_toDataFormat_2a : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><br /><p>Test</p></div>' );
+
+			assert.areSame( '<br /><p>Test</p>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		test_toDataFormat_2b : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><x:x></x:x><p>Test</p></div>' );
+
+			// IE adds the XML namespace tag.
+			if ( CKEDITOR.env.ie )
+				assert.areSame( '<?xml:namespace prefix="x" /><x:x></x:x><p>Test</p>', getDataProcessor().toDataFormat( element ) );
+			else
+				assert.areSame( '<x:x></x:x><p>Test</p>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		test_toDataFormat_3 : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><x:x><p>Test</p></div>' );
+
+			assert.areSame( '<x:x><p>Test</p></x:x>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		test_toDataFormat_ticket_2774 : function()
+		{
+			var element = new CKEDITOR.dom.element.createFromHtml( '<div><P class=MsoNormal><B><I><SPAN lang=EN-US><o:p>Test</o:p></SPAN></I></B></P></div>' );
+
+			// IE adds the XML namespace tag.
+			if ( CKEDITOR.env.ie )
+				assert.areSame( '<p class="MsoNormal"><b><i><span lang="EN-US"><?xml:namespace prefix="o" /><o:p>Test</o:p></span></i></b></p>', getDataProcessor().toDataFormat( element ) );
+			else
+				assert.areSame( '<p class="MsoNormal"><b><i><span lang="EN-US"><o:p>Test</o:p></span></i></b></p>', getDataProcessor().toDataFormat( element ) );
+		},
+
+		name : document.title
+	};
+})() );
+
+	//]]>
+	</script>
+</head>
+<body>
+</body>
+</html>
Index: /CKEditor/branches/prototype/_source/tests/plugins/styles/styles.html
===================================================================
--- /CKEditor/branches/prototype/_source/tests/plugins/styles/styles.html	(revision 2916)
+++ /CKEditor/branches/prototype/_source/tests/plugins/styles/styles.html	(revision 2917)
@@ -2,5 +2,5 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>CKEDITOR.styles Plugin</title>
+	<title>Plugin: styles</title>
 	<link rel="stylesheet" type="text/css" href="../../test.css" />
 	<script type="text/javascript" src="../../../../ckeditor_source.js"></script>
Index: /CKEditor/branches/prototype/_source/tests/testall.html
===================================================================
--- /CKEditor/branches/prototype/_source/tests/testall.html	(revision 2916)
+++ /CKEditor/branches/prototype/_source/tests/testall.html	(revision 2917)
@@ -13,4 +13,9 @@
 	'core/ckeditor2',
 	'core/editor',
+	'core/env',
+	'core/event',
+	'core/scriptloader',
+	'core/tools',
+	'core/xml',
 	'core/dom/document',
 	'core/dom/element',
@@ -18,9 +23,6 @@
 	'core/dom/range',
 	'core/dom/window',
-	'core/env',
-	'core/event',
-	'core/scriptloader',
-	'core/tools',
-	'core/xml',
+	'core/htmlparser/fragment',
+	'plugins/htmldataprocessor/htmldataprocessor',
 	'plugins/styles/styles'
 ];
