XSLT:<xsl:strip-space>不起作用</xsl:strip-space>

时间:2009-07-15 21:55:22

标签: xml xslt

我的应用程序中有一个servlet过滤器,它拦截所有传入的请求,并尝试从传入的XML中删除空格,并将生成的“干净”XML写入响应。我正在使用XSLT来实现这一目标。请参阅下面的XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@*|node()">
<xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

但是,这没有按预期工作。生成的XML与原始XML相同(尽管在样式表中使用了&lt; xsl:strip-space elements =“*”/&gt ;.

请帮助我做到这一点。

的问候,
- Ashish

3 个答案:

答案 0 :(得分:17)

目前尚不清楚您打算将其作为输出,以及您对xsl:strip-whitespace的期望。但有一点需要注意的是,它不会删除所有空白,而只会删除那些在“通常”规则下被认为无关紧要的空白。特别是,来自XSLT 1.0规范:

  

除非文本节点仅包含空格字符,否则永远不会删除它。

所以,例如,这个:

<foo>
  <bar>   </bar>
</foo>

将被删除至:

<foo><bar/></foo>

因为它有3个仅限空格的文本节点(在<foo>之后和<bar>之前,在<bar></bar>之间,以及</bar>之后和之前{ {1}})。

另请注意,由于样式表中包含</foo>,因此最终会转换为:

<xsl:output indent="yes">

在输出中。

另一方面,这个:

<foo>
   <bar/>
<foo>

根本不会被剥离,因为它包含的所有文本节点都不是纯粹的空白节点。

答案 1 :(得分:15)

使用原始问题中的xslt,<xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/></xsl:template>应该可以解决问题。

答案 2 :(得分:2)

将此作为第二个答案添加,因为第一个答案仍然(希望)提供足够的信息以保持它。

假设“trim”意味着“在打开之后和关闭标签之前立即删除所有空格”,那么以下额外的模板规则应该可以解决这个问题:

<xsl:variable name="whitespace">&#x20;&#x9;&#xD;&#xA;</xsl:variable>

<!-- Trim all whitespace at beginning of string -->
<xsl:template name="trim-start">
   <xsl:param name="text"/>
   <xsl:variable name="first-char" select="substring($text, 1, 1)" />
   <xsl:choose>
     <xsl:when test="contains($whitespace, $first-char)">
       <xsl:call-template name="trim-start">
         <xsl:with-param name="text" select="substring($text, 2)" />
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$text" />
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<!-- Trim all whitespace at end of string -->
<xsl:template name="trim-end">
   <xsl:param name="text"/>
   <xsl:variable name="last-char" select="substring($text, string-length($text), 1)" />
   <xsl:choose>
     <xsl:when test="contains($whitespace, $last-char)">
       <xsl:call-template name="trim-end">
         <xsl:with-param name="text" select="substring($text, 1, string-length($text) - 1)" />           </xsl:call-template>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$text" />
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template match="text()">
  <xsl:call-template name="trim-start">
    <xsl:with-param name="text">
      <xsl:call-template name="trim-end">
        <xsl:with-param name="text" select=".">
      </xsl:call-template>
    <xsl:param>
  </xsl:call-template>
</xsl:template>