XSLT将属性从节点转换为另一个节点的元素,并将其从源节点删除

时间:2018-09-21 18:38:57

标签: xslt saxon

给出该xml

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog                    
                   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
  <changeSet author="system (generated)"
           context="legacy"
           id="1537289247911-1"
           objectQuotingStrategy="LEGACY">
    <createTable remarks="Language-dependent texts."
                 tableName="AS_LANGUAGETEXT">
      <column name="TEXTID" remarks="Description identifier" type="NUMBER(9, 0)">
        <constraints primaryKey="true" primaryKeyName="PK_AS_LANGUAGETEXT"/>
      </column>
      <column name="LANGID"
                remarks="Language identifier"
                type="java.sql.Types.VARCHAR(2 ${byteVarcharType})">
        <constraints primaryKey="true" primaryKeyName="PK_AS_LANGUAGETEXT"/>
      </column>
      <column name="TEXT"
                remarks="Description"
                type="java.sql.Types.VARCHAR(4000 ${charVarcharType})"/>
    </createTable>
    <customChange>
      ...
    </customChange>
  </changeSet>
  <changeSet>
    <createTable>
      ...
    </createTable>
    <customChange>
      ...
    </customChange>
  </changeSet>
</databaseChangeLog>

我想:

  • 从源changeset/createTable删除@remarks并将其移至目标changeSet/setTableRemarks,还将@tableName从源复制到目标
  • 从源changeset/createTable/column删除@remarks并将其移至目标changeSet/setColumnRemarks,还将@tableName @columnName从源复制到目标
  • 如果可能,在新的changeSet中使用UUID生成@id
  • 如果可能,在当前修改的changeSet之后添加新创建的changeSet

所以最后它应该像这样:

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog  http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
  <changeSet author="system (generated)"
           context="legacy"
           id="1537289247911-1"
           objectQuotingStrategy="LEGACY">
    <createTable tableName="AS_LANGUAGETEXT">
      <column name="TEXTID" type="NUMBER(9, 0)">
        <constraints primaryKey="true" primaryKeyName="PK_AS_LANGUAGETEXT"/>
      </column>
      <column name="LANGID"
                type="java.sql.Types.VARCHAR(2 ${byteVarcharType})">
        <constraints primaryKey="true" primaryKeyName="PK_AS_LANGUAGETEXT"/>
      </column>
      <column name="TEXT"
                type="java.sql.Types.VARCHAR(4000 ${charVarcharType})"/>
    </createTable>
    <customChange>
      ...
    </customChange>
  </changeSet>
  <changeSet id="621c99b7-eb65-462b-890c-014079e5b44c" author="system">
    <setTableRemarks tableName="AS_LANGUAGETEXT" remarks="Language-dependent texts." />
    <setColumnRemarks tableName="AS_LANGUAGETEXT" columnName="TEXTID" remarks="Description identifier" />
    <setColumnRemarks tableName="AS_LANGUAGETEXT" columnName="LANGID" remarks="Language identifier" />
    <setColumnRemarks tableName="AS_LANGUAGETEXT" columnName="LANGID" remarks="Description" />
  </changeSet>
  <changeSet>
    <createTable>
      ...
    </createTable>
    <customChange>
      ...
    </customChange>
  </changeSet>
  <changeSet>
    <setTableRemarks ... />
    <setColumnRemarks ... />
  </changeSet>
</databaseChangeLog>

编辑:我是使用此模板完成的。 uuid是唯一我不知道该怎么做的,因为saxon-he不支持对Java的调用。因此,我使用了generate-id()函数来代替uuid。

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xpath-default-namespace="http://www.liquibase.org/xml/ns/dbchangelog">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="changeSet[createTable]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="createTable"/>
            <xsl:copy-of select="*[not(self::createTable)]"/>
        </xsl:copy>
        <xsl:element name="changeSet" namespace="http://www.liquibase.org/xml/ns/dbchangelog">
            <xsl:attribute name="id" select="generate-id()" />
            <xsl:attribute name="author">system</xsl:attribute>
            <xsl:element name="setTableRemarks" namespace="http://www.liquibase.org/xml/ns/dbchangelog">
                <xsl:attribute name="tableName" select="createTable//@tableName"/>
                <xsl:attribute name="remarks" select="createTable//@remarks"/>
            </xsl:element>
            <xsl:for-each select="createTable/column">
                <xsl:element name="setColumnRemarks" namespace="http://www.liquibase.org/xml/ns/dbchangelog">
                    <xsl:attribute name="tableName" select="../@tableName"/>
                    <xsl:attribute name="columnName" select="@name"/>
                    <xsl:attribute name="remarks" select="@remarks"/>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <xsl:template match="createTable/@remarks"/>
    <xsl:template match="createTable/column/@remarks"/>

</xsl:transform>

对于转换,我使用的是Saxon-HE:9.8.0-12(java)

1 个答案:

答案 0 :(得分:0)

UUID可以在XSLT中实现。

例如,它已在以下样式表中实现:https://gist.github.com/azinneera/778f69ae6b0049b5edcd69da70072405,您可以包含或导入它,然后使用其uuid:get-uuid()方法。

假定已将其另存为uuid-gen.xsl,并应用于样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:uuid="http://www.uuid.org" 
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xpath-default-namespace="http://www.liquibase.org/xml/ns/dbchangelog">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:include href="uuid-gen.xsl"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="changeSet[createTable]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="createTable"/>
            <xsl:copy-of select="*[not(self::createTable)]"/>
        </xsl:copy>
        <changeSet id="{uuid:get-uuid(.)}" author="system">
            <setTableRemarks>
                <xsl:copy-of select="createTable//(@tableName,@remarks)"/>
            </setTableRemarks>
            <xsl:for-each select="createTable/column">
                <setColumnRemarks>
                    <xsl:copy-of select="../@tableName"/>
                    <xsl:attribute name="columnName" select="@name"/>
                    <xsl:copy-of select="@remarks"/>
                </setColumnRemarks>
            </xsl:for-each>
        </changeSet>
    </xsl:template>

    <xsl:template match="createTable/@remarks"/>
    <xsl:template match="createTable/column/@remarks"/>  
</xsl:stylesheet>