未应用副本上的 XSLT 更改/覆盖属性(使用 saxon ) [英] XSLT change/override attribute on copy-of not applied (using saxon )
问题描述
我有一个这样的 xslt:
I have a xslt like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:db="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:for-each select="db:databaseChangeLog/db:changeSet">
<xsl:if test="name(*[1])='createTable'">
<xsl:result-document href="base/tables/{position()}_{name(*[1])}_{*[1]/@tableName}.xml">
<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-2.0.xsd">
<xsl:copy-of select="."/>
<xsl:copy-of select="../db:changeSet[name(*[1])='createIndex' and *[1]/@tableName= current()/*[1]/@tableName ]" />
</databaseChangeLog>
</xsl:result-document>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="@* | node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="db:changeSet/@author" mode="copy">
<xsl:attribute name="author">
<xsl:value-of select="'sakhunzai'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML 部分文件
<changeSet author="xxx (generated)" id="1358259674512-26">
<createIndex indexName="category_id" tableName="teams" unique="false">
<column name="audience_id"/>
</createIndex>
</changeSet>
<changeSet author="xxx (generated)" id="1358259674512-29">
<createIndex indexName="id" tableName="users" unique="false">
<column name="id"/>
<column name="career_lead_id"/>
</createIndex>
</changeSet>
我想覆盖 changeSet 的属性值(author 和 id).请帮我修复 xslt.
I want to override the attribute values of changeSet (author and id). Please help me fix the xslt.
一切正常,但目标 xml 文件中的 @author 属性值未更改注意:由于 xsltproc 失败,我切换到基于 saxon java 的处理器,例如
Everything is working fine but @author atrribute value is not change in target xml files note: since xsltproc failed to do ,I switched to saxon java based processor e.g
java -jar/usr/local/liquibase/saxon/saxon9he.jar common.xml table.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:db="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:for-each select="db:databaseChangeLog/db:changeSet[db:createTable]">
<xsl:result-document href="base/tables/{position()}_{name(*[1])}_{*[1]/@tableName}.xml">
<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-2.0.xsd">
<xsl:apply-templates select="." mode="copy"/>
<xsl:apply-templates select="../db:changeSet[db:createIndex and *[1]/@tableName= current()/*[1]/@tableName ]" mode="copy"/>
</databaseChangeLog>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
<xsl:template match="node()" mode="copy">
<xsl:copy>
<xsl:attribute name="author">sakhunzai</xsl:attribute>
<xsl:copy-of select="@id|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
推荐答案
不会导致应用模板.它只是创建一个精确的副本.换这条线怎么样
<xsl:copy-of />
does not cause templates to be applied. It just creates an exact copy. How about changing this line
<xsl:template match="db:changeSet/@author">
为此:
<xsl:template match="db:changeSet/@author" mode="copy">
添加此模板:
<xsl:template match="@* | node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
最后改变这个:
<xsl:copy-of select="../db:changeSet[name(*[1])='createIndex' and *[1]/@tableName= current()/*[1]/@tableName ]">
<xsl:copy-of select="."/>
</xsl:copy-of>
为此:
<xsl:apply-templates
select=="../db:changeSet[name(*[1])='createIndex' and *[1]/@tableName = current()/*[1]/@tableName]"
mode="copy" />
顺便说一句,这看起来有点多余:
As a side note, this looks a bit redundant:
<xsl:copy-of select="current()[name()='changeSet']">
<xsl:copy-of select="."/>
</xsl:copy-of>
由于 for-each 循环,当前节点必须具有名称changeSet".我相信这应该足够了:
The current node necessarily has the name "changeSet", by virtue of the for-each loop. I believe this should suffice for that part:
<xsl:copy-of select="." />
完整的 XSLT:
<xsl:stylesheet xmlns:db="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:for-each select="db:databaseChangeLog/db:changeSet">
<xsl:if test="name(*[1])='createTable'">
<xsl:document href="base/tables/{position()}_{name(*[1])}_{*[1]/@tableName}.xml">
<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-2.0.xsd">
<xsl:copy-of select="." />
<xsl:apply-templates select="../db:changeSet[name(*[1])='createIndex' and *[1]/@tableName= current()/*[1]/@tableName ]" mode="copy" />
</databaseChangeLog>
</xsl:document>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="@* | node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="db:changeSet/@author" mode="copy">
<xsl:attribute name="author">
<xsl:value-of select="'sakhunzai'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
我确实认为 XSLT 可以进一步改进,如下所示.喜欢就试试吧:
I do think the XSLT could be further improved like the following. Give it a try if you like:
<xsl:stylesheet xmlns:db="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="db:changeSet" />
<xsl:template match="db:changeSet[db:createTable]">
<xsl:document href="base/tables/{position()}_{name(*[1])}_{*[1]/@tableName}.xml">
<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-2.0.xsd">
<xsl:copy-of select="." />
<xsl:apply-templates select="../db:changeSet[db:createIndex and *[1]/@tableName = current()/*[1]/@tableName ]" mode="copy" />
</databaseChangeLog>
</xsl:document>
</xsl:template>
<xsl:template match="@* | node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="db:changeSet/@author" mode="copy">
<xsl:attribute name="author">
<xsl:value-of select="'sakhunzai'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
这篇关于未应用副本上的 XSLT 更改/覆盖属性(使用 saxon )的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!