我需要编写一个扩展的 XSLT,它不会输出(删除)任何空元素。对于属性,这意味着如果路径的值为空,则不会在输出中填充该属性。对于节点,这意味着如果没有任何数据(空属性或没有属性/数据的子节点),它将不会在输出中填充该节点。下面是一个与棒球相关的示例,以更好地解释我正在寻找的内容。
现在的输出是这样的:
<Baseball>
<Fields>
<Equipment>
<Bats>
<Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" />
<Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" Description="" />
<Bat Brand="" Model="" Length="" Weight="" Description="" />
</Bats>
<Gloves>
<Glove Brand="" Model="" Length="" Description="" />
</Gloves>
</Equipment>
</Fields>
</Baseball>
我需要如何输出:
<Baseball>
<Fields>
<Equipment>
<Bats>
<Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" />
<Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" />
</Bats>
</Equipment>
</Fields>
</Baseball>
我知道我可以通过写入检查值来解决这个问题,但考虑到转换的长度,我希望尽可能避免这种情况。此外,给定我将从中绘制的 XML 结构,给定输出节点的属性将具有彼此不同的路径。例如,输出节点“Bat”中的属性“Brand”可能具有路径“ab/cd/ef/brand”,而属性“Model”可能具有路径“ab/wx/yz/model”。 (我知道我上面的棒球例子不利于这一点)。有没有一种方法可以在不编写两个 XSLT 的情况下实现这一目标?您可以通过 XSLT 传回输出吗?
最佳答案
无需进行两次传递即可实现您的目标。您只需将模板添加到现有样式表中,该模板将匹配不携带信息的节点并抑制它们。
由于您尚未向我们展示您现有的样式表,因此以下示例仅将身份转换默认应用于输入,而两个附加模板则消除了空节点/分支:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- prune the tree -->
<xsl:template match="*[not(descendant::text() or descendant-or-self::*/@*[string()])]"/>
<xsl:template match="@*[not(string())]"/>
</xsl:stylesheet>
应用于当前输出作为测试输入,结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<Baseball>
<Fields>
<Equipment>
<Bats>
<Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite"/>
<Bat Brand="Easton" Model="asdfer" Length="32" Weight="29"/>
</Bats>
</Equipment>
</Fields>
</Baseball>
关于xml - XSL 转换后删除空元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26132339/