使用 XSLT 的子组

sub-group using XSLT

我有一个来源 xml,如下所示。我正在尝试使用 xslt 转换为所需的格式,如下所示

**Sample XML**

 <table>
    <row>
        <tablename>table1</tablename>
        <columnname>col1</columnname>
        <columnDesc>col1_desc</columnDesc>
        <columnDataType>Number</columnDataType>
        <ultimateSourceTable>sourceTable1</ultimateSourceTable>
    </row>
    <row>
        <tablename>table1</tablename>
        <columnname>col1</columnname>
        <columnDesc>col1_desc</columnDesc>
        <columnDataType>Number</columnDataType>
        <ultimateSourceTable>sourceTable2</ultimateSourceTable>
    </row>
    <row>
        <tablename>table2</tablename>
        <columnname>table2_col1</columnname>
        <columnDesc>table2_col1_desc</columnDesc>
        <columnDataType>String</columnDataType>
        <ultimateSourceTable>sourceTable2</ultimateSourceTable>
    </row>
</table> 

当前输出

   <Prod>
<dataBase>
    <physicalTableName>
        <tableName>table1</tableName>
    </physicalTableName>
    <columnList>
        <name>col1</name>
        <name>col1</name>
        <name>table2_col1</name>
    </columnList>
    <finalSourceList>
        <column>
            <columnName>col1</columnName>
            <ultimateSourceTable>sourceTable1</ultimateSourceTable>
        </column>
        <column>
            <columnName>col1</columnName>
            <ultimateSourceTable>sourceTable2</ultimateSourceTable>
        </column>
    </finalSourceList>
    <physicalTableName>
        <tableName>table2</tableName>
    </physicalTableName>
    <columnList>
        <name>col1</name>
        <name>col1</name>
        <name>table2_col1</name>
    </columnList>
    <finalSourceList>
        <column>
            <columnName>table2_col1</columnName>
            <ultimateSourceTable>sourceTable2</ultimateSourceTable>
        </column>
    </finalSourceList>
</dataBase>

期望输出:

<Prod>
    <dataBase>
        <physicalTableName>
            <tableName>table1</tableName>
        </physicalTableName>
        <columnList>
            <name>col1</name>
            <columnDesc>col1_desc</columnDesc>
            <columnDataType>Number</columnDataType>
        </columnList>
        <finalSourceList>
            <column>
                <columnName>col1</columnName>
                <ultimateSourceTable>sourceTable1</ultimateSourceTable>
            </column>
            <column>
                <columnName>col1</columnName>
                <ultimateSourceTable>sourceTable2</ultimateSourceTable>
            </column>
        </finalSourceList>
        <physicalTableName>
            <tableName>table2</tableName>
        </physicalTableName>
        <columnList>
            <name>table2_col1</name>
            <columnDesc>table2_col1_desc</columnDesc>
            <columnDataType>String</columnDataType>
        </columnList>
        <finalSourceList>
            <column>
                <columnName>table2_col1</columnName>
                <ultimateSourceTable>sourceTable2</ultimateSourceTable>
            </column>
        </finalSourceList>
    </dataBase>
</Prod>

XSLT:

      <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="xml" version="1.0" encoding="UTF-8"
                indent="yes" />
            <xsl:template match="/">
                <Prod>
                    <xsl:apply-templates />
                </Prod>
            </xsl:template>
            <xsl:key name="kElsByGroup" match="row" use="tablename" />
            <xsl:key name="TableColByGroup" match="row" use="concat(tablename,'|',columnname)" />
            <xsl:template match="row">
                <xsl:apply-templates />
            </xsl:template>
            <xsl:template
                match="row[generate-id()=generate-id(key('kElsByGroup',tablename)[1])]">
                <dataBase>
                    <physicalTableName>
                        <tableName>
                            <xsl:value-of select="tablename"></xsl:value-of>
                        </tableName>
                    </physicalTableName>
                    <columnList>
                        <xsl:for-each
                                           select="//row[generate-id()=generate-id(key('TableColByGroup',concat(tablename,'|',columnname))[1])]">
                            <xsl:element name="column">
                                <name>
                                    <xsl:value-of
                                                        select="columnname"></xsl:value-of>
                                </name>
                            </xsl:element>
                        </xsl:for-each>
                    </columnList>
                    <finalSourceList>
                        <xsl:for-each
                                            select="key('kElsByGroup',tablename)">
                            <xsl:element name="column">
                                <columnName>
                                    <xsl:value-of
                                                        select="columnname"></xsl:value-of>
                                </columnName>
                                <sourceTable>
                                    <xsl:value-of
                                                        select="ultimateSourceTable"></xsl:value-of>
                                </sourceTable>
                            </xsl:element>
                        </xsl:for-each>
                    </finalSourceList>
                </dataBase>
            </xsl:template>
            <xsl:template
                match="row[not(generate-id()=generate-id(key('kElsByGroup',tablename)[1]))]" />
        </xsl:stylesheet>

所以,我基本上只想在我的 columnList 标记中具有唯一值。我正在尝试使用 muenchian 分组进行子分组,但是我的 columnList 标记中仍然有 2 个 col1 条目。有人可以帮我吗?

源中的单个 table 元素包含不同 table 的 row 看来您可以使用模式处理两次 row 来解决它,一次创建结果 table 的数据,第二次创建每个结果的详细信息 table:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="table" match="row" use="tablename"/>

  <xsl:key name="col" match="row" use="concat(tablename, '|', columnname)"/>

  <xsl:template match="table">
      <Prod>
          <dataBase>
             <xsl:apply-templates select="row[generate-id() = generate-id(key('table', tablename)[1])]" mode="table"/>
          </dataBase>
      </Prod>
  </xsl:template>

  <xsl:template match="row" mode="table">
      <physicalTableName>
          <xsl:value-of select="tablename"/>
      </physicalTableName>
      <columnList>
          <xsl:apply-templates select="key('table', tablename)[generate-id() = generate-id(key('col', concat(tablename, '|', columnname))[1])]/columnname"/>
      </columnList>
      <finalSourceList>
          <xsl:apply-templates select="key('table', tablename)"/>
      </finalSourceList>
  </xsl:template>

  <xsl:template match="row/columnname">
      <name>
          <xsl:value-of select="."/>
      </name>
  </xsl:template>

  <xsl:template match="row">
      <column>
          <xsl:apply-templates select="*[not(self::tablename)]" mode="source-list"/>
      </column>
  </xsl:template>

  <xsl:template match="row/columnname" mode="source-list">
      <columnName>
          <xsl:value-of select="."/>
      </columnName>
  </xsl:template>

  <xsl:template match="row/ultimateSourceTable" mode="source-list">
      <xsl:copy-of select="."/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/naZYrpu/1