将其他xmlns:xsi属性添加到XML元素

时间:2013-08-20 07:32:01

标签: xml xslt namespaces

我定义了以下XML:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="ns0.com" xsi:schemaLocation="ns0.com ns0.xsd">
   <ns1:elementA xmlns:ns1="ns1.com" xsi:schemaLocation="ns1.com ns1.xsd"/>
   <ns2:elementB xmlns:ns2="ns2.com" xsi:schemaLocation="ns2.com ns2.xsd"/>
</ns0:container>

问题在于,使用应用程序只接受容器内部的元素(不幸的是,使用字符串切割容器),然后缺少命名空间xsi的定义。

我想将xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance 添加到容器的每个子元素 - 这将是一个reduntant规范,但不应该导致任何问题。

所以这是我想得到的结果:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="container.com" xsi:schemaLocation="ns0.com ns0.xsd">
   <ns1:elementA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="ns1.com" xsi:schemaLocation="ns1.com ns1.xsd" />
   <ns2:elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="ns2.com" xsi:schemaLocation="ns2.com ns2.xsd"/>
</ns0:container>

这是我的XSLT,我尝试了几个选项,但无法做到:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ns0="ns0.com"
    xmlns:ns1="ns1.com"
    xmlns:ns2="ns2.com">
    <xsl:output method="xml" indent="no"/>

    <xsl:template match="ns0:container/*">
        <xsl:copy>
            <!-- Here I want to add the xmlns:xsi as attribute -->
            <xsl:attribute name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>
            <!-- But this does not work - how should I do that? -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template> 

</xsl:stylesheet>

如何向使用XSLT的元素添加其他xmlns:xsi =“”?

2 个答案:

答案 0 :(得分:1)

我建议修复执行字符串处理而不是XML处理的代码,因为我认为你不能用XSLT添加名称空间声明。

你所能做的只是

<xsl:template match="ns0:container/*">
    <xsl:copy>
      <xsl:copy-of select="../namespace::*"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

但是使用xsl:copy无论如何都会复制范围内的命名空间节点,并且在序列化结果树时,如果XSLT处理器的序列化器已经在父元素或祖先元素上输出,则它们将不会创建命名空间声明。

答案 1 :(得分:1)

尝试这样的事情

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns0="ns0.com">
    <xsl:output method="xml" indent="no"/>
    <xsl:template match="ns0:container/*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/*">
        <xsl:element name="{name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="/*/@xsi:*">
        <xsl:attribute name="other:{local-name()}" namespace="{namespace-uri()}">
            <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"?>
<xsl:stylesheet version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>
    <xsl:template match="/*">
        <xsl:element name="{name()}" namespace="{namespace-uri()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="/*/@xsi:*">
        <xsl:attribute name="other:{local-name()}" namespace="{namespace-uri()}">
            <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中你也有声明ns0命名空间(xmlns:ns0 =“container.com”)的拼写错误。我认为你的意思是(xmlns:ns0 =“ns0.com”)