This doesn't seem to be about XSLT, but rather about the RTF implementation. I've been trying out various options using 2013, and there's definitely some quirkiness in there.
If the RTF were being treated as an XML document in the normal sense, then I'd expect the following XSLT to do what you want:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Of course, an RTF isn't really an XML document, but rather a fragment thereof, potentially with multiple top-level nodes, so Tridion first creates a document with a root element before the XSLT processing takes place They used to use "body" for this, and I suspect they still do, but I wasn't able to prove it. This used to take place all in the browser, but in 2013 it seems there's a back-end service to take care of the transforms. (Maybe that's a strategy to avoid issues with different browsers?)
In my experiments, "/" doesn't seem to get matched at all, although ISTR I had more success with "/body", or was it "/*". In any case, getting this right using the RTF XSLT is probably more trouble than it's worth.
I'd say, in this case, steer clear of the "filtering" XSLT. What you are after, in any case is correctly templated output. For this, your best bet is probably to read the XML of the RTF into an XML document object (XMLDocument, XDocument, whatever). Then you can simply work with the nodes to inject an xhtml:p at the top if it doesn't exist, and then push it through an XSLT to strip the namespace. Or you could do it all in an XSLT, but at least then you're working with an XML document that you've loaded and that you control. Of course, YMMV for 2011, but perhaps at least if you work with your own DOM, you have a very good expectation that your work will upgrade nicely.