You're only outputting a <p> element if the following condition is true:
<xsl:if test="(@*) or (translate(text(),' ','')!='') and (normalize-space(translate(text(),' ',''))!='')">
The first part @* is false for all three p elements because none of them have attributes.
The second part (translate(text(),' ','')!='') is false for all three p elements because none of them has a non-whitespace text node as a child.
Perhaps your intent was to test the string value of the <p> element rather than looking only at its immediate text nodes? That would be string(.) (or just .) in place of text().
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference