1
4

7 回答 7

3

dsteinweg让我走上了正轨……我最终做了:

<xsl:template match="b">
    <xsl:if test="./* or ./text()">
        <xsl:element name="b">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:if>
</xsl:template>
于 2008-11-18T15:20:04.723 回答
3

此转换忽略任何没有任何子节点的 <b> 元素。在此上下文中的节点是指元素、文本、注释或处理指令节点。

<xsl:stylesheet 版本="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:输出省略-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
      <xsl:复制>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:模板>

    <xsl:template match="b[not(node()]"/>
</xsl:样式表>

请注意,这里我们使用了最基本的 XSLT 设计模式之一——使用身份转换并为特定节点覆盖它。

将只为名为“b”的元素且没有(任何节点)子节点的节点选择覆盖模板。这个模板是空的(没有任何内容),所以其应用的效果是匹配节点被忽略/丢弃,并且不在输出中重现。

这种技术非常强大,被广泛用于此类任务,也可用于重命名、更改内容或属性、将子节点或兄弟节点添加到任何可以匹配的特定节点(可以使用除命名空间节点之外的任何类型的节点作为 <xsl:template/> 的“匹配”属性中的匹配模式

希望这有帮助。

干杯,

迪米特·诺瓦切夫

于 2008-11-18T20:48:34.403 回答
2

我想知道这是否可行?

<xsl:template match="b">
  <xsl:if test="b/text()">
    ...
于 2008-11-18T15:08:03.857 回答
1

看看这是否可行。

<xsl:template match="b">
  <xsl:if test=".!=''">
    <xsl:element name="b">
     <xsl:apply-templates/>
    </xsl:element>
  </xsl:if>
</xsl:template>
于 2008-11-18T15:22:32.597 回答
1

另一种方法是执行以下操作:

<xsl:template match="b[not(text())]" />

<xsl:template match="b">
  <b>
    <xsl:apply-templates/>
  </b>
</xsl:template>
于 2008-11-18T16:33:21.890 回答
1

您可以将所有逻辑放在谓词中,并设置一个模板以仅匹配您想要的内容并将其删除:

<xsl:template match="b[not(node())] />

这假设您稍后在转换中有一个身份模板,听起来就像您所做的那样。这将自动复制任何带有内容的“b”标签,这就是你想要的:

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

编辑:现在像下面的 Dimitri 一样使用 node()。

于 2008-11-18T17:24:35.720 回答
0

如果您有权更新原始 XML,则可以尝试在根元素上使用xml:space=preserve

<html xml:space="preserve">
...
</html>

这样,空的 <b> </b> 标记中的空间被保留,因此可以与 XSLT 中的 <b /> 区分开来。

<xsl:template match="b">
   <xsl:if test="text() != ''">
   ....
   </xsl:if>
</xsl:template>
于 2008-11-18T15:30:15.577 回答