从使用XSL生成的HTML中删除空格

时间:2012-05-14 00:54:14

标签: xslt xhtml xslt-2.0 removing-whitespace

背景

在生成HTML时保持可读的XSL源代码,而不会在句子和终止标点符号之间引入空格。来自Rethinking XSLT

  

XSLT样式表中的空格特别成问题,因为它有两个目的:(1)格式化XSLT样式表本身; (2)用于指定空格应该在XSLT处理的XML数据的输出中的位置。

问题

XSL模板包含以下代码:

  <xsl:if test="@min-time &lt; @max-time">
    for
    <xsl:value-of select="@min-time" />
    to
    <xsl:value-of select="@max-time" />
    minutes
  </xsl:if>

  <xsl:if test="@setting">
    on <xsl:value-of select="@setting" /> heat
  </xsl:if>
  .

例如,这会生成以下输出(完全如图所示的空白):

    for
    2
    to
    3
    minutes
  .

所有主流浏览器都会产生:

for 2 to 3 minutes .
除了单词minutes和标点符号之间的空格外,

几乎无瑕疵。所需的输出是:

for 2 to 3 minutes.

可以通过删除XSL模板中的缩进和换行来消除空间,但这意味着有丑陋的XSL源代码。

解决方法

最初,所需的输出包装在变量中,然后按如下方式写出:

<xsl:value-of select="normalize-space($step)" />.

这一直有效,直到我尝试将<span>元素包装到变量中。 <span>元素从未出现在生成的HTML代码中。以下代码也不正确:

<xsl:copy-of select="normalize-space($step)" />.

技术细节

样式表已经使用:

<xsl:strip-space elements="*" />
<xsl:output indent="no" ... />

相关

问题

您如何告诉XSLT处理器消除该空间?

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以将标识模板应用于修剪文本节点空间的附加模板,而不是使用copy-of。您只需在第一个解决方法中创建一个变量。

你打电话:

<li><xsl:apply-templates select="$step" mode="nospace" />.</li>

模板:

<xsl:template match="text()" mode="nospace" priority="1" >
    <xsl:value-of select="normalize-space(.)" />
</xsl:template>

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

答案 1 :(得分:2)

<强>予。这种转变:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="t[@max-time > @min-time]">
  <span>
    <xsl:value-of select=
      "concat('for ', @min-time, ' to ', @max-time, ' minutes')"/>
  </span>
  <xsl:apply-templates select="@setting"/>
  <xsl:text>.</xsl:text>
 </xsl:template>

 <xsl:template match="@setting">
  <span>
    <xsl:value-of select="concat(' on ', ., ' heat')"/>
  </span>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(未显示任何内容!):

<t min-time="2" max-time="3" setting="moderate"/>

会产生想要的正确结果:

<span>for 2 to 3 minutes</span>
<span> on moderate heat</span>.

,浏览器将其显示为

2到3分钟  在适度的热量。

对此XML文档应用相同的转换时

<t min-time="2" max-time="3"/>

再次产生正确的,想要的结果

<span>for 2 to 3 minutes</span>.

,浏览器将其显示为

2至3分钟。


<强> II。布局(可视)解决方案:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" xmlns:gen="gen:gen" xmlns:gen-attr="gen:gen-attr"
 exclude-result-prefixes="my gen">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:layout>
  <span>for <gen-attr:min-time/> to <gen-attr:max-time/> minutes</span>
  <gen-attr:setting><span> on <gen:current/> heat</span></gen-attr:setting>
  <gen:literal>.</gen:literal>
 </my:layout>

 <xsl:variable name="vLayout" select="document('')/*/my:layout/*"/>
 <xsl:variable name="vDoc" select="/"/>

 <xsl:template match="node()|@*">
   <xsl:param name="pCurrent"/>
     <xsl:copy>
       <xsl:apply-templates select="node()|@*">
       <xsl:with-param name="pCurrent" select="$pCurrent"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:apply-templates select="$vLayout">
   <xsl:with-param name="pCurrent" select="$vDoc/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="gen-attr:*">
  <xsl:param name="pCurrent"/>
  <xsl:value-of select="$pCurrent/@*[name() = local-name(current())]"/>
 </xsl:template>

 <xsl:template match="gen-attr:setting">
  <xsl:param name="pCurrent"/>
  <xsl:variable name="vnextCurrent" select=
   "$pCurrent/@*[name() = local-name(current())]"/>
  <xsl:apply-templates select="node()[$vnextCurrent]">
    <xsl:with-param name="pCurrent" select="$vnextCurrent"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="gen:current">
  <xsl:param name="pCurrent"/>
   <xsl:value-of select="$pCurrent"/>
 </xsl:template>

 <xsl:template match="gen:literal">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

这种转换让我们了解了如何对所需输出进行可视(骨架)表示,并使用它来“填充”来自源XML文档的所需数据。

结果与第一种解决方案的结果相同。如果这个转换“按原样”运行,它将产生许多命名空间 - 它们是无害的,如果布局在一个单独的XML文件中,则不会生成。