首页 > 解决方案 > xslt 中具有多个键的子组

问题描述

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

示例 XML

<table>
    <row>
        <tablename>table1</tablename>
        <tableDesc>table1_desc</tableDesc>
        <columnname>col1</columnname>
        <columnDesc>col1_desc</columnDesc>
        <columnDataType>Number</columnDataType>
        <ultimateSourceTable>sourceTable1</ultimateSourceTable>
        <ultimateSourceTableDesc>col1sourceTable1_desc</ultimateSourceTableDesc>
    </row>
    <row>
        <tablename>table1</tablename>
        <tableDesc>table1_desc</tableDesc>
        <columnname>col1</columnname>
        <columnDesc>col1_desc</columnDesc>
        <columnDataType>Number</columnDataType>
        <ultimateSourceTable>sourceTable2</ultimateSourceTable>
        <ultimateSourceTableDesc>col1sourceTable2_desc</ultimateSourceTableDesc>
    </row>
    <row>
        <tablename>table2</tablename>
        <tableDesc>table2_desc</tableDesc>
        <columnname>table2_col1</columnname>
        <columnDesc>table2_col1_desc</columnDesc>
        <columnDataType>String</columnDataType>
        <ultimateSourceTable>sourceTable2</ultimateSourceTable>
        <ultimateSourceTableDesc>col1sourceTable2_desc</ultimateSourceTableDesc>
    </row>
</table> 

期望的输出

<Prod>
        <dataBase>
            <physicalTableName>
                <tableName>table1</tableName>
                <tableDescription>table1_desc</tableDescription>
            </physicalTableName>
            <columnList>
                <column>
                <name>col1</name>
                <columnDesc>col1_desc</columnDesc>
                <columnDataType>Number</columnDataType>
                </column>
            </columnList>
            <finalSourceList>
                <column>
                    <columnName>col1</columnName>
                    <ultimateSourceTable>sourceTable1</ultimateSourceTable>
                    <ultimateSourceTableDesc>col1sourceTable1_desc</ultimateSourceTableDesc>
                </column>
                <column>
                    <columnName>col1</columnName>
                    <ultimateSourceTable>sourceTable2</ultimateSourceTable>
                    <ultimateSourceTableDesc>col1sourceTable1_desc</ultimateSourceTableDesc>
                </column>
            </finalSourceList>
            <physicalTableName>
                <tableName>table2</tableName>
                <tableDescription>table2_desc</tableDescription>
            </physicalTableName>
            <columnList>
                <column>
                <name>table2_col1</name>
                <columnDesc>table2_col1_desc</columnDesc>
                <columnDataType>String</columnDataType>
                <column/>
            </columnList>
            <finalSourceList>
                <column>
                    <columnName>table2_col1</columnName>
                    <ultimateSourceTable>sourceTable2</ultimateSourceTable>
                    <ultimateSourceTableDesc>col1sourceTable2_desc</ultimateSourceTableDesc>
                </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 条目。有人可以帮我吗?

标签: xmlxsltxslt-grouping

解决方案


为了将先前的答案塑造成这个问题的解决方案,我想出了

<?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:strip-space elements="*"/>

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

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

  <xsl:template match="row/tablename" mode="table">
      <tableName>
          <xsl:value-of select="."/>
      </tableName>
  </xsl:template>

  <xsl:template match="row/tableDesc" mode="table">
      <tableDescription>
          <xsl:value-of select="."/>
      </tableDescription>
  </xsl:template>

  <xsl:template match="row/*"/>

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

  <xsl:template match="row/columnDesc | row/columnDataType">
      <xsl:copy-of select="."/>
  </xsl:template>

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

  <xsl:template match="row/*" mode="source-list"/>

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

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

</xsl:stylesheet>

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


推荐阅读