This is what I ended up using. Not sure how it compares to the other answers or if it has the same feature-set, but it worked for my case and I don't remember how I got it anymore. If I adjusted one of the answers here or if I found it somewhere else. In either case, it worked for me. Please comment if there are anything that's missing or better in the others and upvote them :)
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<!--
Pulls namespace declarations up towards root node.
-->
<template match="@* | text() | processing-instruction() | comment()">
<copy />
</template>
<template match="*">
<copy copy-namespaces="no">
<for-each-group group-by="local-name()" select="descendant-or-self::*/namespace::*">
<copy-of select="." />
</for-each-group>
<apply-templates select="@* , node()"/>
</copy>
</template>
</stylesheet>
Note: Don't think this actually merges prefixes (don't remember anymore and unable to test it at the moment), but I used it in the end of ESB processes before returning SOAP messages and the namespaces were cleaned up quite a lot so it does do something at least :p