XSLT从原始文件中删除已处理/选择未处理的数据

时间:2018-06-25 10:16:01

标签: xslt saxon

嗨,我正在处理巨大的文件(50k行),需要了解未处理的节点。 我在考虑这种解决方案:

  • 创建处理文件的副本,并找到匹配的模板,然后将其从复制的文件中删除
  • 创建所有模板的“反向模板”,然后选择所有未处理的内容(这可能行不通)
  • 正常处理文件,然后在原始文件和使用此模板创建的文件之间创建差异。

那么最好的方法是什么?如果需要提供更多详细信息,请告诉我。

这是我的示例xml:

url

这是xslt模板:

<?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 2和saxom 9.8he

谢谢

2 个答案:

答案 0 :(得分:1)

而不是这样做...

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

编辑:感谢Martin Honnen,最终表达式可以简化为此...

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

答案 1 :(得分:0)

我不太确定您所说的“未处理”是什么意思。您的意思是“未通过xsl:apply-templates的任何调用选择”吗?那不是同一回事,当然,一个节点可能使用xsl:for-each等进行处理。此外,我怀疑您只对未通过这种方式“处理”的元素感兴趣,而对其他节点(例如,作为属性和名称空间。

一种可能(或可能不)满足您要求的方法是编写TraceListener。如果将TraceListener附加到转换中,则每当一条指令更改上下文项(这是“正在处理”的另一种定义)时,都会通知它。然后,您的TraceListener可以构建一个Java集合,其中包含所有被触摸的节点,然后可以在处理完成后将其与所有节点的集合区分开。