2010-07-21 32 views
2

使用XSLT,我想知道如何让输出使用样式表的名称空间前缀而不是输入文档的前缀。举例来说,由于这个非常简单的文档:将XSLT输入文档前缀映射到首选值

<?xml version="1.0"?> 
<a:node xmlns:a="urn:schemas:blah:"/> 

而下面的XSL转换:

<?xml version="1.0"?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:blah="urn:schemas:blah:" version="2.0"> 
    <xsl:output indent="yes"> 
    <xsl:template match="/blah:node"> 
     <xsl:copy/><!-- marked --> 
    </xsl:template> 
</xsl:transform> 

我可以告诉大家,处理器(Saxon8如果它的事项)承认前缀'的等价blah:'和'a:',但例如fn:in-scope-prefixes()不显示'blah',只显示'a'。更改上述的<!-- marked -->行:

<node><xsl:value-of select="in-scope-prefixes(.)"/></node> 

输出:

<?xml version="1.0" encoding="UTF-8"?> 
<node xmlns:blah="urn:schemas:blah:">xml a</node> 

我该如何映射输入前缀“a”到“嗒嗒”不知道事先输入文件调用前缀“一“? (所以<xsl:namespace-alias/>将不适用于我。)

作为进一步的上下文,如果它指向更好的解决方案,这是为了查看外部生成的XML文档。外部进程使用自动生成的前缀'a:','b:','c:'等创建输入文档。我希望能够使用'友好'命名空间前缀显示这些前缀。

更新:所述的被范围前缀()行为是由the definition of Statically known namespaces

+0

好问题(1)。查看我的答案以获取完整的XSLT 1.0和XSLT 2.0解决方案。 – 2010-07-22 01:50:58

回答

3

该转化无论在XSLT 1.0和XSLT 2.0(只是改变version属性)):

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

    <my:namespaces> 
    <ns prefix="blah" uri="urn:schemas:blah:"/> 
    <ns prefix="foo" uri="uff:anotherNamespace"/> 
    </my:namespaces> 

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

<xsl:template match= 
"*[namespace-uri()=document('')/*/my:namespaces/*/@uri]"> 
    <xsl:variable name="vNS" select= 
    "document('')/*/my:namespaces/* 
        [@uri=namespace-uri(current())]"/> 
    <xsl:element name="{$vNS/@prefix}:{local-name()}" 
     namespace="{namespace-uri()}"> 
    <xsl:copy-of select= 
    "namespace::*[not(. = namespace-uri(current()))]"/> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 

份数任何XML文档,并且只替换为选择的命名空间与本文档使用前缀我们指定的前缀。

当此XML文档上施加:

<t> 
    <a:node xmlns:a="urn:schemas:blah:"/> 
    <b:node xmlns:b="urn:schemas:blah:"/> 
    <c:node xmlns:c="uff:anotherNamespace"/> 
</t> 

有用结果产生

<t> 
    <blah:node xmlns:blah="urn:schemas:blah:"/> 
    <blah:node xmlns:blah="urn:schemas:blah:"/> 
    <foo:node xmlns:foo="uff:anotherNamespace"/> 
</t> 
+0

非常好。易于添加命名空间+前缀对,以及未改变的前缀可以很好地通过原样传递。 – benizi 2010-07-22 21:38:30

+0

一如既往的完美解决方案。 – Tomalak 2010-07-27 17:16:06

0

解释看一看本说明书为<xsl:namespace-alias ...>顶层元素。我相信它会完成你想要的。

+0

我特别提到的规范不起作用。 :-)我又看了一遍。它似乎对前缀名称进行操作,而不是名称空间URI。所以,在外部过程的一次运行中'urn:schemas:blah:'是'a:'而在另一次运行中'b:'会阻止它在这里工作,对吧? – benizi 2010-07-21 21:40:01

1

如何恒等变换加上这个模板:

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

我不能肯定,这是最优雅的方式做,在XSLT 2.0,但它的作品。

+0

看起来它最终会为我工作(使用此作为第一遍来清理前缀名称,然后使用旧的XSLT作为第二遍)。有没有一种很好的方法来获取在根元素上声明的命名空间?实际上,如果我有,则命名空间节点将附加到而不是。 – benizi 2010-07-21 22:00:19