Q: XSLT escape all entities except     I have a small problem with xslt
i have this text
newline<br /> <br /> newline<br /> <br /> <br /> newline<br /> <br /> <br /> newline<br /> <br /> <b>asdasdasd</b><br /> <br /> <script>alert(0)</script>

I want to escape all entities except <p> <br> <b> <a>, therefore when i use
<xsl:value-of select="page/@post_content" disable-output-escaping="yes"/>

to be able to bold text, insert an link ... etc, but <script> tag to be escaped but not stripped with strip_tags ... but when i let disable-output-escaping="yes" i get a message, so there is XSS vulnerability here ...
my php code is
$hrefs->item(0)->setAttribute("post_content",nl2br($PostContent));

So how can i do this?
PS : I'm very concerned about security! Thanks.

A: XSLT isn't really designed for this, whilst you could do it using XSLT 2.0 using a Regular Expression, this is not the version of XSLT you are using and PHP currently doesn't use XSLT 2 by default. You better doing it in your back-end programming language (such as PHP). 
I realise you say you don't want to use strip_tags is there any reason for it? It does allow you to specify what tags you are able to keep. 

A: You're going to have a hard time doing this with XSLT if you put the post_content into an attribute value, as the attribute's just going to contain one big long string. What happens if the user enters invalid HTML?
If you put the xml directly into an element called 'post_content' instead, you can use these templates:
<xsl:template match="post_content">
  <xsl:apply-templates mode="post" />
</xsl:template>

<xsl:template match="*" mode="post">
  <xsl:value-of select="concat('&lt;',name(),'&gt;')" />
  <xsl:apply-templates mode="post"/>
  <xsl:value-of select="concat('&lt;/',name(),'&gt;')" />
</xsl:template>

<xsl:template match="p | br | b | a" mode="post">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" mode="post"/>
    </xsl:copy>
</xsl:template>

It's a little crude, but basically, the idea is that any p, br, b or a elements are picked up by the last template and copied 'as-is', and anything else is picked up by the * template, and rather than using an actual element, it outputs escaped text instead. The first template is just there to make sure any elements within it are processed using the 'post' mode, so these templates won't accidentally process anything else they shouldn't.
