xslt - 位置()!=最后()不工作
问题描述
我有一个像这样的 XML:
<ast>
<group>
<Set>
<location line="1" column="22" offset="22"/>
<group>
<Id value="foo">
<location line="1" column="31" offset="31"/>
</Id>
</group>
<group>
<Function>
<location line="1" column="22" offset="22"/>
<end-location line="1" column="49" offset="49"/>
<group>
<Id value="a">
<location line="1" column="35" offset="35"/>
</Id>
<Id value="b">
<location line="1" column="37" offset="37"/>
</Id>
</group>
<group>
<Return>
<location line="1" column="40" offset="40"/>
<Number value="0">
<location line="1" column="47" offset="47"/>
</Number>
</Return>
</group>
</Function>
</group>
</Set>
...
</group>
</ast>
我用这个模板处理:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text()" /><!-- remove blanks -->
<xsl:template match="Set[group[position()=1]/Id][group[position()=2]/Function]">
<function-def>
<xsl:attribute name="name">
<xsl:value-of select="group[position()=1]/Id/@value" />
<xsl:text>(</xsl:text>
<xsl:apply-templates select="group[position()=2]/Function" />
<xsl:text>)</xsl:text>
</xsl:attribute>
<xsl:copy-of select="group/Function/location" />
<xsl:copy-of select="group/Function/end-location" />
</function-def>
</xsl:template>
<xsl:template match="Function/group[position()=1]/Id">
<xsl:value-of select="@value" />
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
</xsl:template>
</xsl:stylesheet>
但是position() != last()
最后一个模板上的条件不起作用。为什么?
输出呈现为:
<?xml version="1.0"?>
<function-def name="foo(a,b,)">...
虽然它应该是:
<?xml version="1.0"?>
<function-def name="foo(a,b)">...
解决方案
它正在工作,但不是你想象的那样......
在你的第一个模板中,你有这个xsl:apply-templates
<xsl:apply-templates select="group[position()=2]/Function" />
但是你没有模板匹配Function
,所以 XSLT 的内置模板规则启动了,就是这个......
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
这将选择Group
没有模板的元素。现在,当它这样做时,<xsl:apply-templates/>
它将选择所有子节点,其中包括用于缩进 XML 的空文本节点。
问题是当您进行测试时,您正在测试position() = last()
元素在已选择的所有子节点的集合中的位置,其中包括文本节点。last 后面有一个空的文本节点id
,所以id
可能是最后一个id
元素,但不是最后一个子节点。
一种解决方案是告诉 XSLT 去除空文本节点,这样它id
就会成为最后一个子节点
<xsl:strip-space elements="*" />
或者,您可以添加模板匹配group
,并明确选择仅id
节点
<xsl:template match="Function/group[position()=1]">
<xsl:apply-templates select="Id" />
</xsl:template>
推荐阅读
- python - 如何提取/拆分数据框中的列表列以分隔唯一列?
- scala - 提供的示例中泛型参数的 Scala 编译问题
- xamarin - Xamarin fontawesome 图标显示为带有 x 的正方形
- c - 我们可以将 unsigned char 传递给 inet_ntop()
- sql - Oracle SQL 中的相关子查询和算术
- html - 如何在Angular 7的一个列表中获取多个动态下拉选项值
- azure-devops - 存储库中大型 ARM 模板的团队协作
- pyspark - 加快 PySpark 中的重复 KMeans
- python - Python:使用 zipfile 库将子文件夹解压缩到主文件夹
- wordpress - 有没有办法改变 Typerocket 编辑器的配置?