我目前正在使用 XSLT 2.0 来尝试处理大量数据。我的目标是为整个数据中特定节点的唯一出现调用特定模板。我不能使用“应用模板”,因为我有其他需要根据不同逻辑使用的模板。xml 的结构如下:
<root>
<row>
<date>date1</date>
<child>
<ID>001</ID>
</child>
</row>
<row>
<date>date2</date>
<child>
<ID>002</ID>
</child>
</row>
<row>
<date>date1</date>
<child>
<ID>002</ID>
</child>
</row>
<row>
<date>date3</date>
<child>
<ID>002</ID>
</child>
</row>
</root>
理想情况下,我会在这种情况下调用模板两次,因为有两个唯一的 ID 001 和 002,无论该 ID 上出现多少日期。我见过几个例子,人们要么使用 Keys 要么使用前面的兄弟方法;但是,我似乎永远无法正确使用语法。我尝试了以下方法:
被调用的模板:
<xsl:template name='doSomething'/>
<xsl:value-of select='child/ID'/>
<xsl:value-of select='date'/>
</template>
=====================
<xsl:for-each select='/root/row[not(child/ID = current()child/ID)]
<xsl:call-template name='doSomething'/>
</xsl:for-each>
=====================
<xsl:key name='IDs' match='root/row/child/ID' use='.'/>
<xsl:for-each select='root/row[generate-id() = generate-id(key("IDs",.)[1])]>
<xsl:call-template name='doSomething'/>
</xsl:for-each>
=====================
<xsl:for-each select='root/row/child/ID[not(. = preceding-sibling::row/child/ID)]>
<xsl:call-template name='doSomething'/>
</xsl:for-each>
如果这是可怕的编码,我深表歉意,因为这是我第一次尝试使用 XSLT 进行如此复杂的操作,但我仍然无法理解键的使用以及轴语法的工作原理。我通常在 2.0 中使用 for-each-group。但是,在这里尝试 for-each-group 时,我得到所有条目而不是唯一条目,这让我觉得我不完全理解分组的工作原理。我最初的尝试是这样的:
<xsl:for-each-group select='root/row' group-by='child/ID'>
<xsl:call-template name='doSomething'/>
</xsl:for-each-group>
=====================
我也试过这个:
<xsl:for-each-group select='root/row' group-by='child/ID[1]'>
<xsl:call-template name='doSomething'/>
</xsl:for-each-group>
=====================
我知道这并不完全正确,但我没有想法,只是在试验。任何解决此问题的指导或帮助将不胜感激。提前感谢您提供的任何帮助。
这是我想要的输出:
001日期1 002日期2
但是,我得到:
001日期1 002日期2 002日期1 002日期3
编辑:感谢您的反馈,我意识到我遗漏了相当重要的代码部分。每个 ID 也有相关的日期,代表交易日期。虽然我可以使用 for-each-group 按 ID 分组,但我继续获取与该 ID 关联的所有日期,并且我只想调用唯一 ID 的模板,而不是包含该 ID 的所有条目 - 这就是正在发生。我添加了一个样本输出和当前输出。
我相信我可能误解了 apply-template 的工作原理。我想如果我使用 apply-templates 它将应用 xslt 中的所有模板。因为我有 4 个在特定条件下使用的其他模板。实际输入的 xml 有大约 40 个子节点,用于处理逻辑和信息。
我希望澄清,如果您需要更多详细信息,请告诉我。
编辑:
在做了更多研究之后,似乎使用密钥对我来说是一个好方法;但是,我似乎无法使语法正确。这是我的尝试,有人可以帮我纠正吗?
<xsl:key name='IDs' match='child' use='ID'/>
<xsl:template match='/'>
<xsl:for-each select='root/row/child[generate-id(.) = generate-id(key("IDs", ID)[1])]>
<xsl:call-template name='doSomething'/>
</xsl:for-each>
</xsl:template>
提前感谢您的任何澄清。