Select 节点的属性相对于当前节点的属性
Select node with attribute relative to current node's attribute
我有一些 XML 看起来像这样:
<root>
<node id="2_1" name="FOO" />
<node id="2_2" class="child" />
<node id="2_3" class="child" />
<node id="2_4" class="child" />
<node id="3_1" name="BAR" />
<node id="3_2" class="child" />
<node id="3_3" class="child" />
<node id="3_4" class="child" />
</root>
即一个child
的父节点id
始终共享相同的前缀,但以_1
结尾,所有子节点后缀从2开始递增。
我正在尝试生成类似于以下内容的输出:
<groups>
<group id="2_1">
<child id="2_2" />
<child id="2_3" />
<child id="2_4" />
</group>
<group id="3_1">
<child id="3_2" />
<child id="3_3" />
<child id="3_4" />
</group>
</groups>
我有这个 XSLT 来获取组,但我不确定如何 select 子项:
<xsl:template match="/">
<groups>
<xsl:for-each select="/root/node[@name]">
<group>
<xsl:attribute name="id">
<xsl:value-of select="@id" />
</xsl:attribute>
</group>
</xsl:for-each>
</groups>
</xsl:template>
我这样做的方式正确吗?我想我需要一个接受参数的模板,但我不确定如何为该参数分配当前组的 id
值。
实际上,尽管有我的评论,但您无需在此处完成分组。如果确实规则组 ID 总是以 _1
结尾并且子元素以更大的数字结尾,您可以稍微简化它。
您仍然会创建一个密钥,但只匹配
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
然后,如果您从选择 _1
元素开始,则可以使用键
获取子元素
<xsl:apply-templates
select="key('nodes', substring-before(@id, '_'))[substring-after(@id, '_') != '1']" />
试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
<xsl:template match="root">
<groups>
<xsl:apply-templates select="node[substring-after(@id, '_') = '1']" />
</groups>
</xsl:template>
<xsl:template match="node[substring-after(@id, '_') = '1']">
<group id="{@id}">
<xsl:apply-templates select="key('nodes', substring-before(@id, '_'))[substring-after(@id, '_') != '1']" />
</group>
</xsl:template>
<xsl:template match="node">
<child id="{@id}">
</child>
</xsl:template>
</xsl:stylesheet>
或者,如果 "group" 元素始终具有 name
属性,而子项没有,您可以将其稍微简化为...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
<xsl:template match="root">
<groups>
<xsl:apply-templates select="node[@name]" />
</groups>
</xsl:template>
<xsl:template match="node[@name]">
<group id="{@id}">
<xsl:apply-templates select="key('nodes', substring-before(@id, '_'))[not(@name)]" />
</group>
</xsl:template>
<xsl:template match="node">
<child id="{@id}">
</child>
</xsl:template>
</xsl:stylesheet>
我有一些 XML 看起来像这样:
<root>
<node id="2_1" name="FOO" />
<node id="2_2" class="child" />
<node id="2_3" class="child" />
<node id="2_4" class="child" />
<node id="3_1" name="BAR" />
<node id="3_2" class="child" />
<node id="3_3" class="child" />
<node id="3_4" class="child" />
</root>
即一个child
的父节点id
始终共享相同的前缀,但以_1
结尾,所有子节点后缀从2开始递增。
我正在尝试生成类似于以下内容的输出:
<groups>
<group id="2_1">
<child id="2_2" />
<child id="2_3" />
<child id="2_4" />
</group>
<group id="3_1">
<child id="3_2" />
<child id="3_3" />
<child id="3_4" />
</group>
</groups>
我有这个 XSLT 来获取组,但我不确定如何 select 子项:
<xsl:template match="/">
<groups>
<xsl:for-each select="/root/node[@name]">
<group>
<xsl:attribute name="id">
<xsl:value-of select="@id" />
</xsl:attribute>
</group>
</xsl:for-each>
</groups>
</xsl:template>
我这样做的方式正确吗?我想我需要一个接受参数的模板,但我不确定如何为该参数分配当前组的 id
值。
实际上,尽管有我的评论,但您无需在此处完成分组。如果确实规则组 ID 总是以 _1
结尾并且子元素以更大的数字结尾,您可以稍微简化它。
您仍然会创建一个密钥,但只匹配
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
然后,如果您从选择 _1
元素开始,则可以使用键
<xsl:apply-templates
select="key('nodes', substring-before(@id, '_'))[substring-after(@id, '_') != '1']" />
试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
<xsl:template match="root">
<groups>
<xsl:apply-templates select="node[substring-after(@id, '_') = '1']" />
</groups>
</xsl:template>
<xsl:template match="node[substring-after(@id, '_') = '1']">
<group id="{@id}">
<xsl:apply-templates select="key('nodes', substring-before(@id, '_'))[substring-after(@id, '_') != '1']" />
</group>
</xsl:template>
<xsl:template match="node">
<child id="{@id}">
</child>
</xsl:template>
</xsl:stylesheet>
或者,如果 "group" 元素始终具有 name
属性,而子项没有,您可以将其稍微简化为...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="nodes" match="node" use="substring-before(@id, '_')" />
<xsl:template match="root">
<groups>
<xsl:apply-templates select="node[@name]" />
</groups>
</xsl:template>
<xsl:template match="node[@name]">
<group id="{@id}">
<xsl:apply-templates select="key('nodes', substring-before(@id, '_'))[not(@name)]" />
</group>
</xsl:template>
<xsl:template match="node">
<child id="{@id}">
</child>
</xsl:template>
</xsl:stylesheet>