使用 XSLT 1.0 基于节点值进行稍微复杂的分组

Slightly complex grouping based on node values using XSLT 1.0

我的要求有点复杂 one.I 必须只使用 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 转换为更简单的:

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

例如:

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

2)列出所有<CASEID>在不同<row>中相等的<ISSUEID>&<ISSUEBA>并移动到新标签[=下22=] 在最近创建的 <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>
</results>

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

在你之前的问题中() the answer mentioned about using a technique called Muenchian Grouping in XSLT 1.0。在你的例子中,你有嵌套分组。你首先按 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 分组,您需要 select 每个组的第一个元素,就像这样

<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>