仅从父元素修剪空白

时间:2010-10-22 04:28:49

标签: xslt whitespace trim

我想修剪XML中p标签内的前导空格,所以:

<p>  Hey, <em>italics</em> and <em>italics</em>!</p>

成为这个:

<p>Hey, <em>italics</em> and <em>italics</em>!</p>

(修剪尾随空格不会受到伤害,但并非强制性。)

现在,我知道normalize-whitespace()应该这样做,但如果我尝试将它应用于文本节点..

<xsl:template match="text()">
  <xsl:text>[</xsl:text>
  <xsl:value-of select="normalize-space(.)"/>
  <xsl:text>]</xsl:text>
</xsl:template>

...它分别应用于每个文本节点(在括号中)并将它们吸干:

[Hey,]<em>[italics]</em>[and]<em>[italics]</em>[!]

我的XSLT看起来基本上是这样的:

<xsl:template match="p">
    <xsl:apply-templates/>
</xsl:template>

那么有什么方法可以让apply-templates完成,然后在输出上运行normalize-space,这应该做对了吗?

3 个答案:

答案 0 :(得分:5)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="p//text()[1][generate-id()=
                                      generate-id(ancestor::p[1]
                                                  /descendant::text()[1])]">
        <xsl:variable name="vFirstNotSpace"
                      select="substring(normalize-space(),1,1)"/>
        <xsl:value-of select="concat($vFirstNotSpace,
                                     substring-after(.,$vFirstNotSpace))"/>
    </xsl:template>
</xsl:stylesheet>

输出:

<p>Hey, <em>italics</em> and <em>italics</em>!</p>

编辑2 :更好的表达(现在只有三个函数调用)。

编辑3 :匹配第一个后代文本节点(如果它是文本节点,则不仅仅是第一个节点)。感谢@ Dimitre的评论。

现在,通过此输入:

<p><b>  Hey, </b><em>italics</em> and <em>italics</em>!</p>

输出:

<p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>

答案 1 :(得分:4)

我会做这样的事情:

<xsl:template match="p">
    <xsl:apply-templates/>
</xsl:template>

<!-- strip leading whitespace -->
<xsl:template match="p/node()[1][self::text()]">
  <xsl:call-template name="left-trim">
     <xsl:with-param name="s" value="."/>
  </xsl:call-template>
</xsl:template>

如果它是文本节点,这将从<p>元素的初始节点子节点中剥离左空格。如果它不是第一个节点子节点,它将不会从第一个文本节点子节点剥离空间。例如。在

<p><em>Hey</em> there</p>

我故意避免从“那里”前面剥离空间,因为这会使文字在浏览器中渲染时一起运行。如果您确实要删除该空格,请将匹配模式更改为

match="p/text()[1]"

如果您还想删除尾随空格,正如标题可能暗示的那样,请添加以下两个模板:

<!-- strip trailing whitespace -->
<xsl:template match="p/node()[last()][self::text()]">
  <xsl:call-template name="right-trim">
     <xsl:with-param name="s" value="."/>
  </xsl:call-template>
</xsl:template>

<!-- strip leading/trailing whitespace on sole text node -->
<xsl:template match="p/node()[position() = 1 and
                              position() = last()][self::text()]"
              priority="2">
   <xsl:value-of select="normalize-space(.)"/>
</xsl:template>

左侧修剪和右侧修剪模板的定义位于Trim Template for XSLT(未经测试)。对于具有大量<p> s的文档,它们可能会很慢。如果您可以使用XSLT 2.0,则可以使用

替换调用模板
  <xsl:value-of select="replace(.,'^\s+','')" />

  <xsl:value-of select="replace(.,'\s+$','')" />

(感谢Priscilla Walmsley。)

答案 2 :(得分:2)

你想要

 <xsl:template match="text()">
  <xsl:value-of select=
   "substring(
       substring(normalize-space(concat('[',.,']')),2),
       1,
       string-length(.)
              )"/>
 </xsl:template>

这将字符串包装在"[]"中,然后执行normalize-string(),最后删除包装字符。