.next();
does select the very next sibling, not the child div elements. However, to ensure that you select the next sibling that is actually a div, you should use .next("div");
.
$("#id-3").before($("#id-3").next("div"));
The code above works with the example you gave as long as you change your last div's id to "id-4".
Or, you can copy and paste this code for a working example:
<html>
<head>
<title>Div Swap Test Page</title>
<style type="text/css">
#id-1,#id-2,#id-3,#id-4 {height: 50px; margin:10px 0; border:solid 1px #000}
#id-3 {border:solid 1px #D00}
#id-4 {border:solid 1px #0D0}
</style>
</head>
<body>
<div id="id-1"><div>This is div #1</div><span>I am first.</span></div>
<div id="id-2"><div>This is div #2</div><span>I am second.</span></div>
<div id="id-3"><div>This is div #3</div><span>I am third.</span></div>
<div id="id-4"><div>This is div #4</div><span>I am last.</span></div>
<p><button id="btn"><span>Swap</span></button></p>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$("#btn").click(function() {
$("#id-3").before($("#id-3").next("div"));
});
});
</script>
</html>