XSLT выводит два документа на основе переменной массива - PullRequest
0 голосов
/ 28 мая 2019

У меня есть 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>

Я хотел бы вывести все changeSet s, где sql содержит один из tables в один документ и все остальные (который не 't содержать имя таблицы) в другой документ.Я думал о добавлении материала к переменной и в конце выведите две переменные, но это не работает (или я не знаю, как обрабатывать дальше).

<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 голосов
/ 28 мая 2019

Рассмотрим следующий упрощенный пример:

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

...