XSLT基于数组变量输出两个文档

时间:2019-05-28 10:07:49

标签: xslt xslt-2.0

我的xml文件的结构如下:

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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" id="65D7AFA9-17F1-4406-997E-D2B42A0E9008" dbms="oracle">
        <sql>GRANT SELECT,INSERT,UPDATE,DELETE ON ${dbSchema}.CATALOG TO ${appUser}</sql>
        <rollback>REVOKE SELECT,INSERT,UPDATE,DELETE ON ${dbSchema}.CATALOG FROM ${appUser}</rollback>
    </changeSet>
    <changeSet author="system" id="E2731435-DCEE-4B7E-BA60-20A87E75227A" dbms="oracle">
        <sql>GRANT SELECT,INSERT,UPDATE,DELETE ON ${dbSchema}.CATALOGATTRIBUTE TO ${appUser}</sql>
        <rollback>REVOKE SELECT,INSERT,UPDATE,DELETE ON ${dbSchema}.CATALOGATTRIBUTE FROM ${appUser}</rollback>
    </changeSet>
    <changeSet author="system" id="65D7AFA9-17F1-4406-997E-D2B42A0E9008" dbms="oracle">
        <createTable ...>
    </changeSet>

</databaseChangeLog>

我想将其中sql包含changeSet之一的所有tables输出到一个文档,并将所有其他(不包含表名)输出到另一文档。我正在考虑将内容附加到变量,最后打印两个变量,但这不起作用(或者我不知道如何进一步处理)。

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xpath-default-namespace="http://www.liquibase.org/xml/ns/dbchangelog"
               xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
               xmlns:uuid="http://uuid.util.java"
               exclude-result-prefixes="uuid">

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

    <xsl:variable name="tables"
                  select="('CATALOG','CATALOGATTRIBUTE','EVENTTYPES')"/>

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


    <xsl:template match="changeSet[sql]">
        <xsl:variable name="changeSet" select="."/>
        <xsl:variable name="sql" select="sql"/>
        <xsl:for-each select="$tables">
            <!--<xsl:variable name="selected" select="sql[contains(text(),concat('${dbSchema}.', ., ' '))]"/>-->
            <xsl:variable name="tableName">
                <xsl:value-of select="."/>
                <xsl:value-of select="' '"/>
            </xsl:variable>
            <xsl:choose>
                <xsl:when test="contains($sql, $tableName)">
                    <xsl:copy-of select="$changeSet"/>
                </xsl:when>
                <xsl:otherwise>

                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:transform>

我能以某种方式收集所有与changeSet匹配的tables,然后收集所有changeSets不匹配的东西吗?

ps:我正在使用Saxon-HE-9.8.0-14进行处理。

谢谢

1 个答案:

答案 0 :(得分:0)

请考虑以下简化示例:

XML

<databaseChangeLog>
    <changeSet>
        <sql>ALPHA,BRAVO,CHARLIE</sql>
    </changeSet>
    <changeSet>
        <sql>BRAVO,CHARLIE,DELTA</sql>
    </changeSet>
    <changeSet>
        <sql>DELTA,ECHO,FOXTROT</sql>
    </changeSet>
    <changeSet>
        <sql>FOXTROT,GOLF,HOTEL</sql>
    </changeSet>
</databaseChangeLog>

XSLT 2.0

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

<xsl:param name="tables" select="('BRAVO', 'GOLF')"/>

<xsl:template match="/databaseChangeLog">
    <xsl:variable name="group1" select="changeSet[some $t in $tables satisfies contains(sql, $t)]" />
    <xsl:copy>
        <group1>
            <xsl:copy-of select="$group1"/>
        </group1>
        <group2>
            <xsl:copy-of select="changeSet except $group1"/>
        </group2>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog>
   <group1>
      <changeSet>
        <sql>ALPHA,BRAVO,CHARLIE</sql>
      </changeSet>
      <changeSet>
        <sql>BRAVO,CHARLIE,DELTA</sql>
      </changeSet>
      <changeSet>
        <sql>FOXTROT,GOLF,HOTEL</sql>
      </changeSet>
   </group1>
   <group2>
      <changeSet>
        <sql>DELTA,ECHO,FOXTROT</sql>
      </changeSet>
   </group2>
</databaseChangeLog>

演示https://xsltfiddle.liberty-development.net/jyRYYiP


更好的解决方案是使用tokenize()

XSLT 2.0

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

<xsl:param name="tables" select="('BRAVO', 'GOLF')"/>

<xsl:template match="/databaseChangeLog">
    <xsl:variable name="group1" select="changeSet[tokenize(sql, ',') = $tables]" />
    <xsl:copy>
        <group1>
            <xsl:copy-of select="$group1"/>
        </group1>
        <group2>
            <xsl:copy-of select="changeSet except $group1"/>
        </group2>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

演示https://xsltfiddle.liberty-development.net/jyRYYiP/1