如果仅使用 XSLT 1.0 存在,则基于节点值进行分组
Grouping based on the node value if only it exists using XSLT 1.0
我的要求有点复杂 one.I 必须只使用 XSLT 1.0。我可以使用 XSLT 2.0 获得解决方案,但我需要使用 1.0 的解决方案。
我有以下输入 xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<row>
<ISSUEID>I6</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>10</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
<row>
<CASEID>C11</CASEID>
<CASEBA>MEDICAID</CASEBA>
<OBJECTID>11</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
</results>
我必须按照以下条件使用 XSLT 将上面的 xml 转换为更简单的:
If I have the <CASEID>
, then <CASE>
tag should be there. If I have
the <ISSUEID>
, then <ISSUE>
tag should be there. If I have the
<OBJECT>
, then <OBJECTID>
tag should be there. The reason behind
this is some of the row elements might have <CASEID>
<ISSUEID>
<OBJECTID>
and some not. A <CASE>
can directly have a <SOURCE>
under it if there is no <ISSUE>
.
1)第一个目标是将所有值相同的<CASEID>
与<CASEBA>
节点一起移动到新的<CASE>
标签下。
例如:
<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
</CASE>
2)列出所有<CASEID>
在不同<row>
中相等的<ISSUEID>
&<ISSUEBA>
,并移动到新标签[=下18=] 在最近创建的 <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>
并将它们移动到新的<SOURCE>
标签下<ISSUE>
标签肯定会在 <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>
<ISSUE>
<ISSUEID>I6</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>10</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
<CASE>
<CASEID>C11</CASEID>
<CASEBA>MEDICAID</CASEBA>
<SOURCE>
<OBJECTID>11</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</CASE>
</results>
如果我没有正确解释我的要求,请原谅我。如果您需要任何其他信息,请务必询问我。如果有人帮助我,那就太好了。
您仍然可以使用 Muenchian 分组解决此问题。如果您最初按 CASEID
分组,但 CASEID
可能不存在,您可以像这样定义第一个键
<xsl:key name="case" match="row" use="string(CASEID)" />
因此,对于第一个键,row
个没有 CASEID
的元素将与一个空字符串匹配并组合在一起。
要在 CASEID
内按 INDEXID
分组,您可以使用这样的键,因为这仍然可以在没有 CASEID
的情况下使用(因为 concat
returns一个字符串)
<xsl:key name="issue" match="row" use="concat(CASEID, '|', ISSUEID)" />
要 select 不同的 CASEID
记录,您可以这样做:
<xsl:apply-templates select="row[generate-id() = generate-id(key('case', string(CASEID))[1])]" mode="case" />
但是,在匹配此模式的 row
元素的模板中,您需要一个 xsl:choose
语句来检查 CASEID
是否存在。如果它们确实存在,您将创建 <CASE>
元素。如果没有,您将应用下一级密钥。
<xsl:choose>
<xsl:when test="CASEID">
<CASE>
<!-- Apply next key -->
</CASE>
</xsl:when>
<xsl:otherwise>
<!-- Apply next key -->
</xsl:otherwise>
</xsl:choose>
试试这个 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="string(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', string(CASEID))[1])]" mode="case" />
</xsl:copy>
</xsl:template>
<xsl:template match="row" mode="case">
<xsl:choose>
<xsl:when test="CASEID">
<CASE>
<xsl:apply-templates select="CASEID|CASEBA" />
<xsl:apply-templates select="key('case', string(CASEID))[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />
</CASE>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="key('case', concat('', CASEID))[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="issue">
<xsl:choose>
<xsl:when test="ISSUEID">
<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:when>
<xsl:otherwise>
<xsl:apply-templates select="key('issue', concat(CASEID, '|', ISSUEID))[generate-id() = generate-id(key('object', concat(CASEID, '|', ISSUEID, '|', OBJECTID))[1])]" mode="object" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="object">
<xsl:if test="OBJECTID">
<SOURCE>
<xsl:apply-templates select="OBJECTID|OBJECTBA" />
</SOURCE>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我的要求有点复杂 one.I 必须只使用 XSLT 1.0。我可以使用 XSLT 2.0 获得解决方案,但我需要使用 1.0 的解决方案。
我有以下输入 xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<row>
<ISSUEID>I6</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<OBJECTID>10</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
<row>
<CASEID>C11</CASEID>
<CASEBA>MEDICAID</CASEBA>
<OBJECTID>11</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</row>
</results>
我必须按照以下条件使用 XSLT 将上面的 xml 转换为更简单的:
If I have the
<CASEID>
, then<CASE>
tag should be there. If I have the<ISSUEID>
, then<ISSUE>
tag should be there. If I have the<OBJECT>
, then<OBJECTID>
tag should be there. The reason behind this is some of the row elements might have<CASEID>
<ISSUEID>
<OBJECTID>
and some not. A<CASE>
can directly have a<SOURCE>
under it if there is no<ISSUE>
.
1)第一个目标是将所有值相同的<CASEID>
与<CASEBA>
节点一起移动到新的<CASE>
标签下。
例如:
<CASE>
<CASEID>C1</CASEID>
<CASEBA>MEDICAID</CASEBA>
</CASE>
2)列出所有<CASEID>
在不同<row>
中相等的<ISSUEID>
&<ISSUEBA>
,并移动到新标签[=下18=] 在最近创建的 <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>
并将它们移动到新的<SOURCE>
标签下<ISSUE>
标签肯定会在 <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>
<ISSUE>
<ISSUEID>I6</ISSUEID>
<ISSUEBA>MEDICAID</ISSUEBA>
<SOURCE>
<OBJECTID>10</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</ISSUE>
<CASE>
<CASEID>C11</CASEID>
<CASEBA>MEDICAID</CASEBA>
<SOURCE>
<OBJECTID>11</OBJECTID>
<OBJECTBA>MEDICAID</OBJECTBA>
</SOURCE>
</CASE>
</results>
如果我没有正确解释我的要求,请原谅我。如果您需要任何其他信息,请务必询问我。如果有人帮助我,那就太好了。
您仍然可以使用 Muenchian 分组解决此问题。如果您最初按 CASEID
分组,但 CASEID
可能不存在,您可以像这样定义第一个键
<xsl:key name="case" match="row" use="string(CASEID)" />
因此,对于第一个键,row
个没有 CASEID
的元素将与一个空字符串匹配并组合在一起。
要在 CASEID
内按 INDEXID
分组,您可以使用这样的键,因为这仍然可以在没有 CASEID
的情况下使用(因为 concat
returns一个字符串)
<xsl:key name="issue" match="row" use="concat(CASEID, '|', ISSUEID)" />
要 select 不同的 CASEID
记录,您可以这样做:
<xsl:apply-templates select="row[generate-id() = generate-id(key('case', string(CASEID))[1])]" mode="case" />
但是,在匹配此模式的 row
元素的模板中,您需要一个 xsl:choose
语句来检查 CASEID
是否存在。如果它们确实存在,您将创建 <CASE>
元素。如果没有,您将应用下一级密钥。
<xsl:choose>
<xsl:when test="CASEID">
<CASE>
<!-- Apply next key -->
</CASE>
</xsl:when>
<xsl:otherwise>
<!-- Apply next key -->
</xsl:otherwise>
</xsl:choose>
试试这个 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="string(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', string(CASEID))[1])]" mode="case" />
</xsl:copy>
</xsl:template>
<xsl:template match="row" mode="case">
<xsl:choose>
<xsl:when test="CASEID">
<CASE>
<xsl:apply-templates select="CASEID|CASEBA" />
<xsl:apply-templates select="key('case', string(CASEID))[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />
</CASE>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="key('case', concat('', CASEID))[generate-id() = generate-id(key('issue', concat(CASEID, '|', ISSUEID))[1])]" mode="issue" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="issue">
<xsl:choose>
<xsl:when test="ISSUEID">
<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:when>
<xsl:otherwise>
<xsl:apply-templates select="key('issue', concat(CASEID, '|', ISSUEID))[generate-id() = generate-id(key('object', concat(CASEID, '|', ISSUEID, '|', OBJECTID))[1])]" mode="object" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="object">
<xsl:if test="OBJECTID">
<SOURCE>
<xsl:apply-templates select="OBJECTID|OBJECTBA" />
</SOURCE>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>