XSLT 1.0条件标签处理:仅首次同名attr保留<remove-all-values>
问题:XSLT 1.0 实现同名属性仅首次保留
<remove-all-values>标签 源XML文档
<instance class-name="Deelnemer"> <attr attr-name="achternaam"> <value>McFly</value> </attr> <attr attr-name="geslacht"> <value>MAN</value> </attr> <attr attr-name="geboortedatum"> <value>1968-03-14</value> </attr> <attr attr-name="verzorgers"> <value>{"uuid":"f5a8fecd-7ea6-499e-a8a6-c6eb20e582b8","volgnummer":1}</value> </attr> <attr attr-name="verzorgers"> <value>{"uuid":"54748d2b-b2bf-4362-8520-4c4827a6660c","volgnummer":2}</value> </attr> </instance>
期望转换结果
<modify-attr attr-name="achternaam"> <remove-all-values/> <add-value> <value>McFly</value> </add-value> </modify-attr> <modify-attr attr-name="geslacht"> <remove-all-values/> <add-value> <value>MAN</value> </add-value> </modify-attr> <modify-attr attr-name="geboortedatum"> <remove-all-values/> <add-value> <value>1968-03-14</value> </add-value> </modify-attr> <modify-attr attr-name="verzorgers"> <remove-all-values/> <add-value> <value>{"uuid":"f5a8fecd-7ea6-499e-a8a6-c6eb20e582b8","volgnummer":1}</value> </add-value> </modify-attr> <modify-attr attr-name="verzorgers"> <add-value> <value>{"uuid":"54748d2b-b2bf-4362-8520-4c4827a6660c","volgnummer":2}</value> </add-value> </modify-attr>
可行XSLT 1.0解决方案
提供两种实现思路,均能满足需求:
方法1:使用preceding-sibling直接判断
通过检查当前<attr>节点之前是否存在同名节点,决定是否输出<remove-all-values>标签:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 匹配根节点,遍历所有attr子节点 --> <xsl:template match="/instance"> <xsl:apply-templates select="attr"/> </xsl:template> <!-- 处理每个attr节点 --> <xsl:template match="attr"> <modify-attr attr-name="{@attr-name}"> <!-- 仅当前是第一个同名attr时,输出remove-all-values --> <xsl:if test="not(preceding-sibling::attr[@attr-name = current()/@attr-name])"> <remove-all-values/> </xsl:if> <add-value> <xsl:copy-of select="value"/> </add-value> </modify-attr> </xsl:template> </xsl:stylesheet>
方法2:使用key分组(更高效)
对于节点数量较多的场景,key分组利用索引机制,性能更优,通过判断当前节点是否为分组内第一个节点控制标签输出:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 按attr-name分组定义key --> <xsl:key name="attrGroup" match="attr" use="@attr-name"/> <!-- 匹配根节点,遍历所有attr子节点 --> <xsl:template match="/instance"> <xsl:apply-templates select="attr"/> </xsl:template> <!-- 处理每个attr节点 --> <xsl:template match="attr"> <modify-attr attr-name="{@attr-name}"> <!-- 判断是否为当前分组的第一个节点 --> <xsl:if test="generate-id() = generate-id(key('attrGroup', @attr-name)[1])"> <remove-all-values/> </xsl:if> <add-value> <xsl:copy-of select="value"/> </add-value> </modify-attr> </xsl:template> </xsl:stylesheet>
说明
- 方法1逻辑直观,但节点数量较多时,每次判断需遍历前置节点,性能会下降。
- 方法2通过索引分组,判断效率更高,适合处理大型XML文档。
内容的提问来源于stack exchange,提问作者Petro Hagenauw
相关产品推荐
相关产品推荐

