2014-02-25 64 views
0

我想使用XSL将默认名称空间定义添加到根元素。然而,问题是,在XSL转换之后,子元素具有我需要防止的属性xmlns=''XSL仅将名称空间定义添加到XML根目录

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 on root only,但在我的情况下,XML中包含更多元素(如示例中所列的元素),所以对我来说这是不可行的。

+1

请注意,在您的预期输出中,'xmlns =“http://www.liquibase.org/xml/ns/dbchangelog”'会为'databaseChangeLog'的所有子元素创建一个_default命名空间_。所以,它不是“仅限根”的名称空间。 –

+0

@MathiasMüller:感谢您的纠正,随时更新问题/标题 –

+1

在您的许可下,我为您的问题添加了一个说明。问题标题看起来不错。 –

回答

2

变化

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

但是,你不复制文本(和其他既不是元素也不属于属性的节点)。 –

+0

我只要求OP更改特定的模板。 –

+0

是的,但该模板复制文本。改变后的模板不会。 –

0

试试这样说:

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

请记住,XSLT,你不创建命名空间声明。相反,您使用正确的扩展名(名称空间URI和本地名称)创建元素,并且序列化程序会在获取名称空间声明之后进行查看。所以你想让changeSet元素在命名空间http://www.liquibase.org/xml/ns/dbchangelog中,你必须在该命名空间中创建它,你不能只在其父元素上放置一个默认的命名空间声明。如果您在与其父级不同的名称空间中创建changeSet元素,序列化程序将添加一个名称空间声明以反映您的(明显的)意图。

+0

感谢您的解释! –

相关问题