Index: _source/core/htmlparser/element.js
===================================================================
--- _source/core/htmlparser/element.js	(revision 7260)
+++ _source/core/htmlparser/element.js	(working copy)
@@ -157,6 +157,39 @@
 		},
 
 		/**
+		 * Whether the provided element is identical this one. An identical element
+		 * has the same name and attributes.
+		 * @param {CKEDITOR.htmlParser.element} otherElement The element to be compared.
+		 * @returns {Boolean} 'true' if the elements are identical.
+		 */
+		isIdentical : function( otherElement )
+		{
+			if ( !otherElement.name || otherElement.name != this.name )
+				return false;
+
+			var attribsA = this.attributes,
+				attribsB = otherElement.attributes,
+				lenA = 0,
+				lenB = 0;
+
+			// Check if all attributes available on A are defined on B.
+			for ( var att in attribsA )
+			{
+				if ( attribsA[ att ] !== attribsB[ att ] )
+					return false;
+				
+				// Count the number of attribs on A.
+				lenA++;
+			}
+
+			// Count the number of attribs on B.
+			for ( att in attribsB )
+				lenB++;
+
+			return lenA == lenB;
+		},
+
+		/**
 		 * Writes the element HTML to a CKEDITOR.htmlWriter.
 		 * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
 		 * @example
Index: _source/core/htmlparser/fragment.js
===================================================================
--- _source/core/htmlparser/fragment.js	(revision 7260)
+++ _source/core/htmlparser/fragment.js	(working copy)
@@ -92,6 +92,9 @@
 						pendingDtd = CKEDITOR.dtd[ pendingName ],
 						currentDtd = currentNode.name && CKEDITOR.dtd[ currentNode.name ];
 
+					if ( pendingElement.ignore )
+						continue;
+
 					if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] || !CKEDITOR.dtd[ newTagName ] ) )
 					{
 						if ( !pendingBRsSent )
@@ -218,6 +221,30 @@
 			// This is a tag to be removed if empty, so do not add it immediately.
 			if ( isRemoveEmpty( element ) )
 			{
+				// The element must be marked to be ignored if there is already another
+				// identical element to be used. (#8322)
+				for ( var i = 0 ; i < pendingInline.length ; i++ )
+				{
+					if ( element.isIdentical( pendingInline[i] ) )
+					{
+						element.ignore = 1;
+						break;
+					}
+				}
+
+				if ( !element.ignore )
+				{
+					// The element must be marked to be ignored if there is already an
+					// identical element on the parents tree. (#8322)
+					var parent = currentNode;
+					while ( parent )
+					{
+						if ( element.isIdentical( parent ) )
+							element.ignore = 1;
+						parent = parent.parent;
+					}
+				}
+
 				pendingInline.push( element );
 				return;
 			}
