基于 XSLT 1.0 的节点值的分组略显复杂



我的要求有点复杂。我只需要使用 XSLT 1.0。我可以使用 XSLT 2.0 获得解决方案,但我需要使用 1.0 的解决方案。

我有以下输入 xml:

<results>
<row>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUEID>I1</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>1</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
<row>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUEID>I2</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>2</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
<row>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUEID>I1</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>extra</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
<row>
<CASEID>C2</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUEID>I3</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>3</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
</results>

我必须按照以下条件使用 XSLT 将上述 xml 转换为更简单的 xml:

1)第一个目标是将新<CASE>标签下所有值相同的<CASEID>与节点一起移动<CASEBA>

例如:

<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
</CASE>

2)列出所有在不同<row><CASEID>相等的<ISSUEID><ISSUEBA>,并将它们移动到新标签下,<ISSUE>最近创建的<CASE>标签中。

例如:

<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUE>
<ISSUEID>I1</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
</ISSUE>
<ISSUE>
<ISSUEID>I2</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
</ISSUE>
</CASE>

3)列出所有在不同<row><ISSUEID>相等的<OBJECTID>,并将它们移动到<ISSUE>标签内的新<SOURCE>标签下,该标签肯定会在<CASE>下。 例如:

<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUE>
<ISSUEID>I1</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>1</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
<SOURCE>
<OBJECTID>extra</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
<ISSUE>
<ISSUEID>I2</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>2</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
</CASE>

最终输出 xml 应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<results>
<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUE>
<ISSUEID>I1</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>1</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
<SOURCE>
<OBJECTID>extra</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
<ISSUE>
<ISSUEID>I2</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>2</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
</CASE>
<CASE>
<CASEID>C2</CASEID>
<CASEBA>MEDICAID</CASEBA>
<ISSUE>
<ISSUEID>I3</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>3</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
</CASE>
</results>

如果我没有正确解释我的要求,请原谅我。如果您需要任何其他信息,请询问我。如果有人帮助我,那就太好了。

在上一个问题(基于节点值转换 xml)中,答案提到了在 XSLT 1.0 中使用一种称为 Muenchian 分组的技术。在您的情况下,您具有嵌套分组。您首先按CASEID分组,然后按CASEIDISSUEID分组,最后按CASEIDISSUEIDOBJECTID分组

这意味着定义三个键

<xsl:key name="case" match="row" use="CASEID" />
<xsl:key name="issue" match="row" use="concat(CASEID, '|', ISSUEID)" />
<xsl:key name="object" match="row" use="concat(CASEID, '|', ISSUEID, '|', OBJECTID)" />

要按CASEID分组,您将选择每个组的第一个元素,如下所示

<xsl:apply-templates select="row[generate-id() = generate-id(key('case', CASEID)[1])]" mode="case" />

(我在这里使用mode,因为最终的 XSLT 将有多个模板匹配row因此您需要区分它们)。

在匹配模板中,要在不同的CASEID值中按ISSUEID分组,您将执行此操作。

<xsl:apply-templates select="key('case', CASEID)[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />

然后,您将在另一个模板中执行类似的按OBJECTID分组的操作。

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="case" match="row" use="CASEID" />
<xsl:key name="issue" match="row" use="concat(CASEID, '|', ISSUEID)" />
<xsl:key name="object" match="row" use="concat(CASEID, '|', ISSUEID, '|', OBJECTID)" />
<xsl:template match="results">
<xsl:copy>
<xsl:apply-templates select="row[generate-id() = generate-id(key('case', CASEID)[1])]" mode="case" />
</xsl:copy>
</xsl:template>
<xsl:template match="row" mode="case">
<CASE>
<xsl:apply-templates select="CASEID|CASEBA" />
<xsl:apply-templates select="key('case', CASEID)[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />
</CASE>
</xsl:template>
<xsl:template match="row" mode="issue">
<ISSUE>
<xsl:apply-templates select="ISSUEID|ISSUEBA" />
<xsl:apply-templates select="key('issue', concat(CASEID, '|', ISSUEID))[generate-id() = generate-id(key('object', concat(CASEID, '|', ISSUEID, '|', OBJECTID))[1])]" mode="object" />
</ISSUE>
</xsl:template>
<xsl:template match="row" mode="object">
<OBJECT>
<xsl:apply-templates select="OBJECTID|OBJECTBA" />
</OBJECT>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

相关内容

  • 没有找到相关文章

最新更新