Xslt 仅从父元素修剪空白
我想修剪XML中p标记中的前导空格,因此:Xslt 仅从父元素修剪空白,xslt,whitespace,trim,Xslt,Whitespace,Trim,我想修剪XML中p标记中的前导空格,因此: <p> Hey, <em>italics</em> and <em>italics</em>!</p> …它分别应用于每个文本节点(括号中),并将其吸干: [Hey,]<em>[italics]</em>[and]<em>[italics]</em>[!] [嘿,][斜体][和][斜体][!] 我的XSLT基本上如下所示: &
<p> Hey, <em>italics</em> and <em>italics</em>!</p>
…它分别应用于每个文本节点(括号中),并将其吸干:
[Hey,]<em>[italics]</em>[and]<em>[italics]</em>[!]
[嘿,][斜体][和][斜体][!]
我的XSLT基本上如下所示:
<xsl:template match="p">
<xsl:apply-templates/>
</xsl:template>
<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>
那么,有没有什么方法可以让应用模板完成,然后在输出上运行normalize space,这样做应该是正确的呢
<xsl:template match="text()">
<xsl:value-of select=
"substring(
substring(normalize-space(concat('[',.,']')),2),
1,
string-length(.)
)"/>
</xsl:template>
这会将字符串包装到
“[]”
,然后执行normalize-string()
,最后删除包装字符。我会这样做:
<xsl:template match="p">
<xsl:apply-templates/>
</xsl:template>
<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>
如果您还想去除尾随空格,正如标题可能暗示的那样,请添加以下两个模板:
<!-- 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>
左修剪和右修剪模板的定义位于(未测试)。对于包含大量
的文档,它们的速度可能较慢。如果可以使用XSLT2.0,则可以将调用模板替换为
<xsl:value-of select="replace(.,'^\s+','')" />
及
(感谢。)此样式表:
<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>
<p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>
嘿,斜体字和斜体字
编辑2:更好的表达式(现在只有三个函数调用)
编辑3:匹配第一个子体文本节点(如果是文本节点,则不只是第一个节点)。感谢@Dimitre的评论
现在,有了这个输入:
<p><b> Hey, </b><em>italics</em> and <em>italics</em>!</p>
嘿,斜体字和斜体字
输出:
<p>Hey, <em>italics</em> and <em>italics</em>!</p>
<p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>
嘿,斜体字和斜体字
问得好+1.有关简单的解决方案,请参见我的答案。:)+一个好问题。请看我的答案,我认为这是目前为止唯一一个符合你要求的答案。你的意思是只前导空格,还是前导和尾随?你能给出一个你想要实现的输出的例子吗?现在还不清楚。您只是想删除第一个text()节点的前导空格吗?换句话说,只保留“嘿”之前的空格,并保留文本节点的尾随空格以及围绕“和”?@Mads:围绕什么和什么?(降价问题)+1我认为它并没有完全达到@jpatokal想要的效果,但它还没有被清楚地表述出来。这提供了从
p/text()[1]
中修剪前导空格所需的所有信息,这是我认为需要的。@LarsH:回答得好。我想你不是想要p/node()[1][self::text()]
而是想要p/node()[self::text()][1]
。最后一个文本节点也是如此。@Dimitre:这不是(a)产生第一个/最后一个文本节点,不管它们是否在任何非文本子节点的“外部”;或者(b)做和我一样的事?请进一步解释,因为我想更好地理解这一点。@Mads,如果p/text()[1]前面有一个元素,如a
,我认为他不想从p/text()[1]
中删除前导空格,是吗?但我同意,让@jpatokal澄清一下。@LarsH:p/node()[1][self::text()]
的意思是:p的第一个节点子节点,但前提是它是文本节点。而您想要的是:p
的所有文本节点子节点中的第一个,我相信方括号用于演示它当前正在做什么(从每个文本节点中去掉前导和尾随空格)。这无法实现所需的输出(尚未明确说明)。@Mads Hansen:如果包装字符仅用于说明目的(这似乎是可能的),则可以在应用normalize-space()
后将其删除。我更新了我的答案,做到了这一点,我想这就是OP想要的。这是目前为止唯一一个规范化文本节点内部空白的答案。这个想法很有趣,但我担心它实际上不起作用——当我尝试时,我得到了“嘿,]斜体和斜体!”?但是+1对于其他答案的有用评论。哇:-)我想我看到了嵌套的substring()调用在做什么,它比递归模板好得多+1@Alejandro:我想你作为拉尔斯有smae问题。我想你不想p/node()[1][self::text()]
而是p/node()[self::text()][1]
。@Dimitre:那和p/text()[1]
一样,但我知道你的意思。+1我想我们有赢家了!这就是我所理解的期望输出。非常好的解决方案。@Alejandro:不完全是,考虑一下:你好
。这将是:(p//text())[1]
<p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>