给出以下XML文档:
<foo>
<bar>
<type>1</type>
<id>1</id>
<a1>0</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>1</id>
<a1>0</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>2</id>
<a1>0</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>2</id>
<a1>0</a1>
<other_stuff/>
</bar>
</foo>
XML元素bar
是列表元素,按类型和ID进行逻辑分组。因此,示例文档包含两个有序列表(type = 1和id = 1,type = 1和id = 2),每个列表包含两个元素。在真实文档中,还有更多不同长度的列表(使用不同的类型和ID)。
现在我需要使用不同的值更新每个列表的第一个元素a1
,例如在以下文件中:
<foo>
<bar>
<type>1</type>
<id>1</id>
<a1>-100</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>1</id>
<a1>0</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>2</id>
<a1>-100</a1>
<other_stuff/>
</bar>
<bar>
<type>1</type>
<id>2</id>
<a1>0</a1>
<other_stuff/>
</bar>
</foo>
在伪SQL中,这可能如下所示:
update bar set a1 = -100 where position() = 1 group by type, id
XSLT 1.0可以实现吗?我认为可以归结为能够编写一个XPath表达式,其结果与我的伪SQL语句相同。
答案 0 :(得分:2)
使用Muenchian grouping标识每个组中的第一个项目并更改子项,使用标识转换复制其余项目:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="new-value" select="-100"/>
<xsl:key name="group" match="bar" use="concat(type, '|', id)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="bar[generate-id() = generate-id(key('group', concat(type, '|', id))[1])]/a1">
<xsl:copy>
<xsl:value-of select="$new-value"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
至于进一步的解释,密钥定义<xsl:key name="group" match="bar" use="concat(type, '|', id)"/>
允许XSLT处理器索引bar
上的concat(type, '|', id)
元素,以便我们可以使用密钥函数,例如key('group', '1|1')
。 bar
concat(type, '|', id)
找到具有bar
值的所有bar[...]
元素。
您只想更改每个组中的第一个bar[. is the first item in its group]
元素,因此我们需要有一种方法来识别谓词内的第一个项目key('group', concat(type, '|', id))
,我们需要找到表达的模式条件
bar[. is the first item in key('group', concat(type, '|', id))]
我们使用is
进入模式的组,因此我们想写一个条件
bar[. is key('group', concat(type, '|', id))[1]]
我们可以在XSLT 2.0中用bar[generate-id() = generate-id(key('group', concat(type, '|', id))[1])]
运算符和模式
bar
使用XSLT 1.0,我们可以使用generate-id表达它,如
中所述[1]
选择/匹配生成的id等于key('group', concat(type, '|', id))
计算的组中第一个(import file
anyVariable = 42
# ...
def aFunc():
file.anyVarible = file.anyVarible + 1
)项的生成ID的{{1}}元素。