Index: /CKEditor/trunk/CHANGES.html
===================================================================
--- /CKEditor/trunk/CHANGES.html	(revision 5395)
+++ /CKEditor/trunk/CHANGES.html	(revision 5396)
@@ -152,4 +152,5 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4459">#4459</a> : [IE] Select element is penetrating the maximized editor in IE6.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/5559">#5559</a> : [IE] The first call of CKEDITOR.editor::setData is affected by iframe cache when loading wysiwyg mode.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5567">#5567</a> : [IE] Remove inline styles in some case doesn't join identical siblings.</li>
 		<li>Updated the following language files:<ul>
 			<li><a href="http://dev.fckeditor.net/ticket/5326">#5326</a> : Catalan;</li>
Index: /CKEditor/trunk/_source/core/dom/element.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/element.js	(revision 5395)
+++ /CKEditor/trunk/_source/core/dom/element.js	(revision 5396)
@@ -1,3 +1,3 @@
-﻿/*
+/*
 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
@@ -778,4 +778,29 @@
 
 		/**
+		 * Whether it's an empty inline elements which has no visual impact when removed.
+		 */
+		isEmptyInlineRemoveable : function()
+		{
+			if ( !CKEDITOR.dtd.$removeEmpty[ this.getName() ] )
+				return false;
+
+			var children = this.getChildren();
+			for ( var i = 0, count = children.count(); i < count; i++ )
+			{
+				var child = children.getItem( i );
+
+				if ( child.type == CKEDITOR.NODE_ELEMENT && child.getAttribute( '_fck_bookmark' ) )
+					continue;
+
+				if ( child.type == CKEDITOR.NODE_ELEMENT && !child.isEmptyInlineRemoveable()
+					|| child.type == CKEDITOR.NODE_TEXT && CKEDITOR.tools.trim( child.getText() ) )
+				{
+					return false;
+				}
+			}
+			return true;
+		},
+
+		/**
 		 * Indicates that the element has defined attributes.
 		 * @returns {Boolean} True if the element has attributes.
@@ -874,4 +899,54 @@
 			}
 		},
+
+		mergeSiblings : ( function()
+		{
+			function mergeElements( element, sibling, isNext )
+			{
+				if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT )
+				{
+					// Jumping over bookmark nodes and empty inline elements, e.g. <b><i></i></b>,
+					// queuing them to be moved later. (#5567)
+					var pendingNodes = [];
+
+					while ( sibling.getAttribute( '_fck_bookmark' )
+						|| sibling.isEmptyInlineRemoveable() )
+					{
+						pendingNodes.push( sibling );
+						sibling = isNext ? sibling.getNext() : sibling.getPrevious();
+						if ( !sibling || sibling.type != CKEDITOR.NODE_ELEMENT )
+							return;
+					}
+
+					if ( element.isIdentical( sibling ) )
+					{
+						// Save the last child to be checked too, to merge things like
+						// <b><i></i></b><b><i></i></b> => <b><i></i></b>
+						var innerSibling = isNext ? element.getLast() : element.getFirst();
+
+						// Move pending nodes first into the target element.
+						while( pendingNodes.length )
+							pendingNodes.shift().move( element, !isNext );
+
+						sibling.moveChildren( element, !isNext );
+						sibling.remove();
+
+						// Now check the last inner child (see two comments above).
+						if ( innerSibling && innerSibling.type == CKEDITOR.NODE_ELEMENT )
+							innerSibling.mergeSiblings();
+					}
+				}
+			}
+
+			return function()
+			{
+				// Merge empty links and anchors also. (#5567)
+				if ( !( CKEDITOR.dtd.$removeEmpty[ this.getName() ] || this.is( 'a' ) ) )
+					return;
+
+				mergeElements( this, this.getNext(), true );
+				mergeElements( this, this.getPrevious() );
+			}
+		} )(),
 
 		/**
Index: /CKEditor/trunk/_source/plugins/styles/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/styles/plugin.js	(revision 5395)
+++ /CKEditor/trunk/_source/plugins/styles/plugin.js	(revision 5396)
@@ -551,5 +551,5 @@
 
 					// Let's merge our new style with its neighbors, if possible.
-					mergeSiblings( styleNode );
+					styleNode.mergeSiblings();
 
 					// As the style system breaks text nodes constantly, let's normalize
@@ -625,5 +625,5 @@
 						 * them before removal.
 						 */
-						mergeSiblings( element );
+						element.mergeSiblings();
 						removeFromElement( this, element );
 
@@ -1058,45 +1058,9 @@
 			{
 				// Check the cached nodes for merging.
-				mergeSiblings( firstChild );
-
-				if ( lastChild && !firstChild.equals( lastChild ) )
-					mergeSiblings( lastChild );
-			}
-		}
-	}
-
-	function mergeSiblings( element )
-	{
-		if ( !element || element.type != CKEDITOR.NODE_ELEMENT || !CKEDITOR.dtd.$removeEmpty[ element.getName() ] )
-			return;
-
-		mergeElements( element, element.getNext(), true );
-		mergeElements( element, element.getPrevious() );
-	}
-
-	function mergeElements( element, sibling, isNext )
-	{
-		if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT )
-		{
-			var hasBookmark = sibling.getAttribute( '_fck_bookmark' );
-
-			if ( hasBookmark )
-				sibling = isNext ? sibling.getNext() : sibling.getPrevious();
-
-			if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT && element.isIdentical( sibling ) )
-			{
-				// Save the last child to be checked too, to merge things like
-				// <b><i></i></b><b><i></i></b> => <b><i></i></b>
-				var innerSibling = isNext ? element.getLast() : element.getFirst();
-
-				if ( hasBookmark )
-					( isNext ? sibling.getPrevious() : sibling.getNext() ).move( element, !isNext );
-
-				sibling.moveChildren( element, !isNext );
-				sibling.remove();
-
-				// Now check the last inner child (see two comments above).
-				if ( innerSibling )
-					mergeSiblings( innerSibling );
+				firstChild.type == CKEDITOR.NODE_ELEMENT && firstChild.mergeSiblings();
+
+				if ( lastChild && !firstChild.equals( lastChild )
+					&& lastChild.type == CKEDITOR.NODE_ELEMENT  )
+					lastChild.mergeSiblings();
 			}
 		}
