在生成HTML时保持可读的XSL源代码,而不会在句子和终止标点符号之间引入空格。来自Rethinking XSLT:
XSLT样式表中的空格特别成问题,因为它有两个目的:(1)格式化XSLT样式表本身; (2)用于指定空格应该在XSLT处理的XML数据的输出中的位置。
XSL模板包含以下代码:
<xsl:if test="@min-time < @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处理器消除该空间?
谢谢!
答案 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文件中,则不会生成。