2010-06-30 60 views
2

XSL样式表应该如下代码到Internet Explorer输出:如何在XSLT输出中保留XML命名空间?

<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下面的模板抛出分析错误:样式表不包含文档元素。 在同一时间火狐删除输出XML命名空间 ...

那么,怎样才能保持我的xml 命名在我的输出?

重要

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

b。以下代码不能解决我的问题:

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

难道我理解正确的话,你想一个命名空间节点添加到每个元素? – 2010-06-30 13:29:32

+0

@Sawa:我必须说我与Dimitre有关,不鼓励MS允许使用xml:namespace和其他非标准元素。更重要的是,这可以通过适当的命名空间声明'xmlns:vml =“urn:schemas-microsoft-com:vml”' – 2010-06-30 18:52:47

回答

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

,这是非常简单的实现

<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文档中的每个元素(如果不是这样,只是让我通过commentand我会删除该知道回答)。

如果是这样,这里是一个简单且有效的方式:

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

我认为你的回答并不包括所有情况。如果样式表必须使用IE浏览器进行客户端解析,那么您会得到以下结果:'El prefijo del espacio de nombres no puede comenzar con la cadena reservada'xml“' – 2010-06-30 14:47:37

+1

@Ajjandro:我没有意识到MSXML3的这种行为哪些IE使用)。嗯......这可能被认为是一个功能和一个错误。事实上,我所使用的所有其他XSLT处理器都允许这样做。事实上MSXML4允许这样做,这意味着它们纠正了MSXML4中的MSXML3错误。没关系,试图在'xml:'命名空间中使用非标准元素是一种粗暴的滥用,我不鼓励作者这么做。 – 2010-06-30 16:13:37

+0

我和你一起劝说不要使用MS所允许的'xml:namespace'和其他非标准元素。更重要的是,这可以通过适当的命名空间声明'xmlns:vml =“urn:schemas-microsoft-com:vml”' – 2010-06-30 18:51:37