我们有以下XSLT可以删除所有级别的空标记。
我们还想指定一些例外。它可以是要避免的特定标记,也可以是要避免的参数化标记列表。例如,如果我们遇到名为SpecialTag
的标记,则应该允许该标记为空。该标签下面的所有内容仍然可以修剪。这可能吗?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(descendant-or-self::*[text()[normalize-space()] | @*])]"/>
</xsl:stylesheet>
答案 0 :(得分:2)
以下是两种方法。根据您的描述,这涉及与元素名称列表进行比较。
XSLT 1.0在其功能集中更受限制 - 特别是在这里影响我们,我们无法与模板match
表达式中的变量进行比较。因此,我们采取直截了当的蛮力方法。
<!-- Test first that the name doesn't match anything we want to keep.
Just add more conditions as needed.
Put the main test at the end (that checks for attributes or text). -->
<xsl:template match="*
[local-name() != 'SpecialTag']
[local-name() != 'OtherSpecialTag']
[local-name() != 'ThirdSpecialTag']
['Add other conditions here.']
[not(descendant-or-self::*[text()[normalize-space()] | @*])]
"/>
在XSLT 2.0中,我们可以与模板match
表达式中的变量进行比较。这是使用变量的一种可能方式,它可能看起来比XSLT 1.0方法更清晰或更易读。
<xsl:variable name="Specials">
<item>SpecialTag</item>
<item>OtherSpecialTag</item>
<item>ThirdSpecialTag</item>
<!-- Add other tag names here. -->
<item>...</item>
</xsl:variable>
<!-- Test first that the name doesn't match anything we want to keep.
Note the syntax - we say `not()` rather than using `!=`,
because `!=` evaluates to true if *any* <item> value doesn't match
the name of the current context element.
Meanwhile, `not(... = ...)` only evaluates to true if *all* of the
<item> values don't match the name of the current context element.
Put the main test at the end (that checks for attributes or text). -->
<xsl:template match="*
[not(local-name() = $Specials/item)]
[not(descendant-or-self::*[text()[normalize-space()] | @*])]
"/>
如果元素没有显式前缀,则函数name()
和local-name()
会生成相同的值。如果他们做有前缀,name()
包含前缀,而local-name()
则不包含前缀。相应地调整上面的示例代码以匹配您的用例。