我想使用 XSL
将默认命名空间定义添加到根元素中。然而,问题是,在XSL
转换后,子元素具有我需要防止的属性xmlns=''
。
XML 输入:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog>
<changeSet author="abc" id="def">
...
</changeSet>
</databaseChangeLog>
预期的 XML 输出:
<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<changeSet author="abc" id="def">
...
</changeSet>
</databaseChangeLog>
我尝试过像这样使用 XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/databaseChangeLog">
<databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<xsl:apply-templates select="node()|@*" />
</databaseChangeLog>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但结果是:
<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<changeSet xmlns="" author="abc" id="def">
...
</changeSet>
</databaseChangeLog>
知道如何解决这个问题吗?
请注意,有一个类似的问题:XSLT xmlns 仅在根目录上,但是在我的情况下,XML 中包含更多元素(只是示例中列出的元素),因此这对我来说不可行。
更改
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
自
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="http://www.liquibase.org/xml/ns/dbchangelog">
<xsl:apply-templates select="node()|@*" />
</xsl:element>
</xsl:template>
请记住,使用 XSLT,您不会创建命名空间声明。相反,您创建具有正确扩展名称(命名空间 URI 加本地名称)的元素,序列化程序负责正确获取命名空间声明。所以你希望 changeSet 元素位于命名空间 http://www.liquibase.org/xml/ns/dbchangelog 中,你必须在该命名空间中创建它,你不能只在其父元素上放置默认命名空间声明。如果在与其父级不同的命名空间中创建 changeSet 元素,序列化程序将添加一个命名空间声明以反映您的(明显)意图。
试试这个方式:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/*">
<databaseChangeLog
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<xsl:apply-templates select="node()|@*" />
</databaseChangeLog>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="http://www.liquibase.org/xml/ns/dbchangelog">
<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="text()|comment()|processing-instruction()" >
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>