XSLT命名空间和默认命名空间问题

时间:2015-02-23 00:48:14

标签: xslt

我是XSLT转型的新手。我的输出xml中有名称空间映射问题。

输入XML是



<m:class xmlns:m="http://www.NotRequirednamespace.com">
         <queryDetails>hello</queryDetails>
</m:class>
&#13;
&#13;
&#13;

我的XSLT看起来像

&#13;
&#13;
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.neededNamespace.com" xmlns:t="http://www.NotRequirednamespace.com" exclude-result-prefixes="t">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <!-- Stylesheet to remove all namespaces from a document -->
    <!-- NOTE: this will lead to attribute name clash, if an element contains
        two attributes with same local name but different namespace prefix -->
    <!-- Nodes that cannot have a namespace are copied as such -->

<xsl:template match="/">
<school xmlns="http://www.neededNamespace.com">
<xsl:apply-templates/>
</school>
</xsl:template>

    <!-- template to copy elements -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | text() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>
&#13;
&#13;
&#13;

输出XML是

&#13;
&#13;
<school xmlns="http://www.neededNamespace.com">
<class xmlns="">
<queryDetails>hello</queryDetails>
</class>
</school>
&#13;
&#13;
&#13;

但我不想在元素类中使用名称默认命名空间(xmlns =&#34;&#34;)。我喜欢将类元素的默认命名空间指定为&#34; http://www.neededNamespace.com&#34;。所以我需要输出xml如下。

&#13;
&#13;
<school xmlns="http://www.neededNamespace.com">
<class>
<queryDetails>hello</queryDetails>
</class>
</school>
&#13;
&#13;
&#13;

我已经尝试了所有我知道的选项。你能帮忙吗?提前谢谢。

2 个答案:

答案 0 :(得分:2)

你真的需要所有代码吗?或者你只是用这个作为咒语,希望它能以某种方式安抚邪恶的灵魂?就像xpath-default-namespace在XSLT 1.0样式表中所做的那样? (答案:要么没有,要么产生致命的错误 - 取决于你的处理器的耐受程度)。

现在,如果您的XML示例具有代表性,那么您需要做的就是:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.neededNamespace.com">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <school>
        <xsl:apply-templates/>
    </school>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

这是做什么的:

  1. 创建名为<school>;
  2. 的新根元素
  3. 为每个现有元素创建一个新元素,并使用现有元素的本地名称命名。
  4. 由于样式表包含默认命名空间的声明,所有新创建的元素(在上面的#1和#2中)都将放在该命名空间中。

    由于您的输入不包含任何属性,因此应该是所有必需的代码。

    如果您担心他们将来可能会添加一些您希望传递给输出的属性,只需将第二个模板更改为:

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>
    

    这假设属性不在命名空间中 - 这是一个非常合理的假设。属性不会继承其父级的名称空间,您很少看到作者明确地将名称放在名称空间中。只有当您真的需要预测这种可能性时,才需要额外的代码来处理属性。

答案 1 :(得分:1)

所以你不想删除“class”元素的命名空间,你想要改变它。使用xsl:element节点的“namespace”属性。

而不是

<xsl:element name="{local-name()}">

你想要

<xsl:element name="{local-name()}" namespace="http://www.neededNamespace.com">