【问题标题】:XSLT namespace and default namespace issue [duplicate]XSLT 命名空间和默认命名空间问题 [重复]
【发布时间】:2015-04-24 06:44:36
【问题描述】:

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

输入的 XML 是

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

我的 XSLT 是这样的

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

输出的 XML 是

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

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

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

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

【问题讨论】:

标签: xslt


【解决方案1】:

您真的需要所有这些代码吗?或者你只是把它当作咒语,希望它能以某种方式安抚邪恶的灵魂?就像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. 创建一个名为&lt;school&gt;的新根元素;
  2. 为每个现有元素创建一个新元素,并使用现有元素的本地名称为其命名。

由于样式表包含默认命名空间的声明,所有新创建的元素(在上面的#1 和#2 中)都将放置在该命名空间中。

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

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

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

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

【讨论】:

    【解决方案2】:

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

    代替

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

    你想要的

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

    【讨论】:

    • 感谢 bjimba 的宝贵意见。在包含您提到的命名空间值之后。我得到了低于预期的输出。 &lt;school xmlns="http://www.neededNamespace.com"&gt; &lt;class xmlns="http://www.neededNamespace.com"&gt; 请注意,我在学校和班级之间还有一些其他名称空间的标签和元素。
    • 我不知道为什么不会这样。它们现在位于正确的命名空间中。根据您的 XSL 处理器,这样说可能比您想要的更冗长。您应该密切注意 Michael 在此处的回答,它比我指向 xsl:element 的命名空间属性的快速指针要详细得多。花时间通过一个好的网站(甚至一本书)来理解 XML 命名空间真的很值得。
    猜你喜欢
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多