如何在xsl中转换字符,其中文本来自处理指令

时间:2011-01-24 23:32:41

标签: html xml xslt escaping

此问题类似于此处提到的问题how to unescape xml with xslt,但略有不同,因为我的文字来自处理指令。

我有这样的指示:

<?xm-mark data="&lt;p>Here is the text&lt;/p>" ?>

我想输出&lt;未编码的数据部分。到目前为止我的尝试是:

<xsl:template match="processing-instruction('xm-mark')">
  <mymark>
  <xsl:value-of select="substring-before(substring-after(., 'data=&quot;'), '&quot;')"
  disable-output-escaping="yes" />
  </mymark>
</xsl:template>

然而,这让我回复了&lt;p>的文字。如果我删除disable-output-escaping =“yes”,我会回到&amplt;(按照我的预期进行双重编码)。既然我不能在我的模板中放置一个值 - 值得知道我是如何对数据进行处理的呢?

2 个答案:

答案 0 :(得分:3)

这是您通过将标记转换为文本来销毁标记时获得的结果。

记住永远不要“设计”这些可怕的事情。

此外,诉诸DOE是一种绝望的迹象,is not guaranteed to work (DOE不是强制性功能和一些主要的XSLT 1.0处理器,例如FF使用的处理器实施它。)

那么,还有什么其他选择

一种可能的解决方案是编写一个扩展函数(在XSLT / XPath版本1.0和2.0中没有这样的标准函数),它接受一个字符串,将其解析为XML并返回生成的XML文档。它会像这样使用:

  <xsl:copy-of select=
      "xx:parse(substring-before(substring-after(., 'data=&quot;'), '&quot;'))/*"/>

答案 1 :(得分:1)

处理说明不需要转义任何内容,它们的解析类似于评论,因为<??>之间的任何内容都完全按原样处理。如果可以的话,你需要修改生成该指令的任何内容来生成它:

<?xm-mark data="<p>Here is the text</p>" ?>

如果你不能这样做,我甚至不会尝试使用XSLT来解析它。

编辑:我应该澄清一下,因为你可能会比你需要的东西更复杂:处理指令没有属性,甚至“和末尾的空格都是'价值的一部分'处理指令节点'。你实际上得到了一个名为xm-mark且值data="<p>Here is the text</p>"的处理指令(包括末尾的空格,这里没有显示); {{ 1}}与data部分一样是值的一部分。

在你的情况下<p>..</p>可能已经足够了,那么处理指令节点的值只是<?xm-mark <p>Here is the text</p>?>,这是你可能感兴趣的全部内容。

编辑:哎哟..好吧,你可以试试这个:            

<p>Here is the text</p>

注意:因为 <xsl:template match="processing-instruction('xm-mark')"> <xsl:element name="mymark"> <xsl:call-template name="unescape"> <xsl:with-param name="input" select="substring-before(substring-after(., 'data=&quot;'), '&quot;')" /> </xsl:call-template> </xsl:element> </xsl:template> <xsl:template name="unescape"> <xsl:param name="input" /> <xsl:choose> <xsl:when test="contains($input, '&amp;lt;')"> <xsl:call-template name="unescape"> <xsl:with-param name="input" select="substring-before($input, '&amp;lt;')" /> </xsl:call-template> <xsl:text>&lt;</xsl:text> <xsl:call-template name="unescape"> <xsl:with-param name="input" select="substring-after($input, '&amp;lt;')" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$input" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 被视为文本而不是标记,所以在使用xslt进行处理时,您需要使用&来引用它。因此,如果在xml文档中“按原样”输出,则处理指令的值实际上表示为&amp;。上面的xsl至少会将其转换为&amp;lt;p&gt;etc..,但如果您想要实际的&lt;p&gt;etc..标记,请使用扩展方法。