XSLT 从原始文件中删除 processed/select 未处理的数据
XSLT remove processed/select unprocessed data from original file
您好,我正在处理大文件(50k 行)并且需要了解未处理的节点。
我在考虑这个解决方案:
- 创建处理文件的副本,当找到匹配的模板时,将其从复制的文件中删除
- 创建 "reverse template" 所有模板和 select 所有未处理的内容(这可能行不通)
- 正常处理文件,然后在原始文件和使用此模板创建的文件之间创建差异。
那么最好的方法是什么?如果需要提供更多详细信息,请告诉我。
这是我的样本 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 和 saxom 9.8he
谢谢
而不是这样做...
<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)" />
我不太清楚你说的 "not processed" 是什么意思。你是说 "not selected by any call on xsl:apply-templates" 吗?这不是一回事,当然,一个节点可能会使用 xsl:for-each 等进行处理。此外,我怀疑您只对不是 "processed" 的元素感兴趣,而不是在其他节点中,例如属性和命名空间。
一种可能(或可能不)满足您的要求的方法是编写 TraceListener。如果您将 TraceListener 附加到您的转换,它会在每次指令更改上下文项时收到通知(这是 "being processed" 的另一个定义)。然后,您的 TraceListener 可以构建一个 Java 集合,其中包含所有被触摸的节点,然后可以在处理完成时将其与所有节点的集合进行区分。
您好,我正在处理大文件(50k 行)并且需要了解未处理的节点。 我在考虑这个解决方案:
- 创建处理文件的副本,当找到匹配的模板时,将其从复制的文件中删除
- 创建 "reverse template" 所有模板和 select 所有未处理的内容(这可能行不通)
- 正常处理文件,然后在原始文件和使用此模板创建的文件之间创建差异。
那么最好的方法是什么?如果需要提供更多详细信息,请告诉我。
这是我的样本 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 和 saxom 9.8he
谢谢
而不是这样做...
<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)" />
我不太清楚你说的 "not processed" 是什么意思。你是说 "not selected by any call on xsl:apply-templates" 吗?这不是一回事,当然,一个节点可能会使用 xsl:for-each 等进行处理。此外,我怀疑您只对不是 "processed" 的元素感兴趣,而不是在其他节点中,例如属性和命名空间。
一种可能(或可能不)满足您的要求的方法是编写 TraceListener。如果您将 TraceListener 附加到您的转换,它会在每次指令更改上下文项时收到通知(这是 "being processed" 的另一个定义)。然后,您的 TraceListener 可以构建一个 Java 集合,其中包含所有被触摸的节点,然后可以在处理完成时将其与所有节点的集合进行区分。