XSLT удалить обработанные / выбрать необработанные данные из исходного файла - PullRequest
0 голосов
/ 25 июня 2018

Привет! Я обрабатываю огромный файл (50 тыс. Строк) и мне нужно знать об узлах, которые не были обработаны. Я думал об этом решении:

  • создать копию обрабатываемого файла и, когда соответствующий шаблон найден, затем удалить его из скопированного файла
  • создать "обратный шаблон" из всех шаблонов и выбрать все, что не было обработано (это, вероятно, не будет работать)
  • обычно обрабатывает файл, а затем создает diff между исходным файлом и файлом, созданным с помощью этого шаблона.

Так, каков наилучший подход для этого? Если есть необходимость предоставить более подробную информацию, дайте мне знать, пожалуйста.

Вот мой пример 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
                   http://www.liquibase.org/xml/ns/dbchangelog">

    <changeSet id="1" author="a">
        <createTable tableName="TABLE1">
            <column></column>
        </createTable>
    </changeSet>

    <changeSet id="1-1" author="a">
        <createSequence sequenceName="SEQ_TABLE1" />
    </changeSet>
    <changeSet id="4" author="A">
        <createTable tableName="TABLE4">
            <column></column>
        </createTable>
    </changeSet>
</databaseChangeLog>

вот шаблон xslt:

<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:variable name="coreTables"
                  select="('TABLE1','TABLE2')"/>


    <xsl:template match="node()[not(self::*)]">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="databaseChangeLog">
        <!-- CORE-->
        <xsl:comment> CORE TABLES </xsl:comment>
        <xsl:apply-templates select="changeSet[createTable/@tableName=$coreTables]"/>
        <xsl:comment>CORE SEQUENCES</xsl:comment>
        <xsl:apply-templates
                select="changeSet[createSequence[starts-with(@sequenceName, 'SEQ_') and substring-after(@sequenceName, 'SEQ_') = $coreTables]]"/>
        <xsl:comment> CORE INDEXES </xsl:comment>
        <xsl:apply-templates select="changeSet[createIndex/@tableName=$coreTables]"/>
        <xsl:comment> CORE FOREIGN CONSTRAINTS </xsl:comment>
        <xsl:apply-templates select="changeSet[addForeignKeyConstraint/@baseTableName=$coreTables]"/>
        <xsl:comment> CORE VIEWS </xsl:comment>
        <xsl:apply-templates select="changeSet[createView/@viewName=$coreTables]"/>
    </xsl:template>

</xsl:transform>

Я использую xslt 2 и саксом 9.8he

Спасибо

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Я не совсем уверен, что вы подразумеваете под "не обработано".Вы имеете в виду "не выбран ни одним вызовом на xsl: apply-templates"?Это не одно и то же, конечно, узел может быть обработан с использованием xsl: for-each и т. Д. Кроме того, я подозреваю, что вас интересуют только элементы, которые не были «обработаны» таким образом, а не другие узлы, такие какв качестве атрибутов и пространств имен.

Один из подходов, который может (или не может) отвечать вашим требованиям, - написать TraceListener.Если вы присоедините TraceListener к вашему преобразованию, он будет получать уведомления каждый раз, когда инструкция изменяет элемент контекста (это еще одно определение «обрабатывается»).Затем ваш TraceListener может создать набор Java, содержащий все затронутые узлы, и затем может отличить его от набора всех узлов после завершения обработки.

0 голосов
/ 25 июня 2018

Вместо этого ...

<xsl:comment> CORE TABLES </xsl:comment>
<xsl:apply-templates select="changeSet[createTable/@tableName=$coreTables]"/>

Сделайте это, чтобы сохранить выбранные элементы

<xsl:variable name="tables" select="changeSet[createTable/@tableName=$coreTables]"/>
<xsl:apply-templates select="$tables" />

И аналогично для других утверждений. Затем, чтобы получить элементы в вашем XML, которые не были сопоставлены, вы можете сделать это ...

<xsl:apply-templates select="changeSet[not(some $set in ($tables | $sequences | $indexes | $fkeys | $views) satisfies $set is .)]" />

Попробуйте этот шаблон

<xsl:template match="databaseChangeLog">
    <!-- CORE-->
    <xsl:comment> CORE TABLES </xsl:comment>
    <xsl:variable name="tables" select="changeSet[createTable/@tableName=$coreTables]"/>
    <xsl:apply-templates select="$tables" />

    <xsl:comment>CORE SEQUENCES</xsl:comment>
    <xsl:variable name="sequences" select="changeSet[createSequence[starts-with(@sequenceName, 'SEQ_') and substring-after(@sequenceName, 'SEQ_') = $coreTables]]"/>
    <xsl:apply-templates select="$sequences"/>

    <xsl:comment> CORE INDEXES </xsl:comment>
    <xsl:variable name="indexes" select="changeSet[createIndex/@tableName=$coreTables]"/>
    <xsl:apply-templates select="$indexes"/>

    <xsl:comment> CORE FOREIGN CONSTRAINTS </xsl:comment>
    <xsl:variable name="fkeys" select="changeSet[addForeignKeyConstraint/@baseTableName=$coreTables]"/>
    <xsl:apply-templates select="$fkeys"/>

    <xsl:comment> CORE VIEWS </xsl:comment>
    <xsl:variable name="views" select="changeSet[addForeignKeyConstraint/@baseTableName=$coreTables]"/>
    <xsl:apply-templates select="$views"/>

    <xsl:comment> UNMATCHED </xsl:comment>
    <xsl:apply-templates select="changeSet[not(some $set in ($tables | $sequences | $indexes | $fkeys | $views) satisfies $set is .)]" />
</xsl:template>

РЕДАКТИРОВАТЬ: Благодаря Мартин Хоннен, окончательное выражение может быть упрощено до этого ...

<xsl:apply-templates select="changeSet except ($tables, $sequences, $indexes, $fkeys, $views)" />
...