如何在XSLT输出中保留XML命名空间?

时间:2010-06-30 09:13:34

标签: xml xslt namespaces

XSL样式表应将以下代码输出到Internet Explorer:

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>

但是当我使用任何XML

执行以下模板时
<xsl:template match="*|node()">
    <xml:namespace prefix="vml"
                   ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>

IE抛出解析错误:样式表不包含文档元素。 同时Firefox在输出中删除了 xml 命名空间......

那么,我如何在输出中保留 xml 命名空间?

重要

一个。我使用的输出方法是 html

湾以下代码无法解决我的问题:

<xsl:template match="*|node()">
    <namespace prefix="vml"
               xmlns="http://www.w3.org/XML/1998/namespace"
               ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>

2 个答案:

答案 0 :(得分:2)

您不能使用保留的xml前缀。使用这样的东西:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dummy="dummy">
<xsl:namespace-alias stylesheet-prefix="dummy" result-prefix="xml"/>
<xsl:template match="/">
    <dummy:namespace prefix="vml"
                   ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>
</xsl:stylesheet>

对于任何输入,您都会得到以下结果:

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml" />

答案 1 :(得分:1)

如果您真的想要问题中显示的结果,那么实现起来非常简单

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>
 </xsl:template>
</xsl:stylesheet>

此转换应用于任何XML文档(未使用)时,会生成所需结果

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>

但是,在我看来,您想要将命名空间节点添加到给定XML文档的每个元素(如果不是这样,请通过注释告诉我,我将删除此答案)。

如果是这样,这是一种简单有效的方法:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:vml="urn:schemas-microsoft-com:vml"
     exclude-result-prefixes="vml">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="vNamespace" select=
     "document('')/*/namespace::*[name()='vml']"/>

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

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

应用于任何文档时,例如

<t>
    <a x="3">
        <b y="4"/>
    </a>
</t>

生成了想要的结果

<t xmlns:vml="urn:schemas-microsoft-com:vml">
   <a x="3">
      <b y="4"/>
   </a>
</t>

乍一看可能会让人感到困惑,因为只有结果的顶部元素明显具有所需的命名空间节点。但是,根据定义(查看 XML Namespace spec ),如果(子)树的根处的元素具有给定的命名空间节点,则其所有后代元素也具有此命名空间节点。即使您将名称空间复制到每个元素,XSLT序列化程序也会将其从除顶部元素之外的所有元素的序列化(文本)表示中删除。

在XSLT 2.0中,您只需使用<xsl:namespace>指令

<xsl:namespace name="vml" select="urn:schemas-microsoft-com:vml"/>