XSLT检查特定元素是否以文本节点开头(为什么这不起作用)

时间:2014-02-06 09:09:09

标签: xml xslt

我不明白为什么使用以下表达式检查元素(在我的情况下为p)是否在文本节点之前:

preceding-sibling::node()[1][self::text()]

无效。这是一个例子来说明:

输入

<div> 
   simply a text node
   <element />
   <p/>
</div>

XSLT

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

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

   <xsl:template match="p">
  <xsl:if test="preceding-sibling::node()[1][self::text()]">
     <br />
  </xsl:if>
  <xsl:copy>
     <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

我原以为<br />没有插入,因为紧接<p />之前的节点是一个元素,而不是文本节点。但是输出是:

<div> 
   simply a text node
   <element/>
   <br/>
   <p/>
</div>

就像我没有<element/>节点一样。有人可以指出我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

这是因为原始<br/><p/>之间的空格(换行符和缩进空格)是它自己的text()节点。

尝试将以下内容添加为xsl:stylesheet ...

的子项
<xsl:strip-space elements="*"/>

答案 1 :(得分:0)

我认为您缺少检查text()值是否为null:

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

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

<xsl:template match="p">
    <xsl:if test="preceding-sibling::node()[1][self::text() = '']">
        <br />
    </xsl:if>
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>