将XSLT输入文档前缀映射到首选值

时间:2010-07-21 21:16:41

标签: xml xslt namespaces prefix

使用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'的情况下,如何将输入前缀'a'映射到'blah'? (所以<xsl:namespace-alias/>对我不起作用。)

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

更新the definition of Statically known namespaces

解释了范围内前缀()行为

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

身份变换加上这个模板怎么样:

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

我不确定这是在XSLT 2.0中实现它的最优雅方式,但它确实有用。

答案 2 :(得分:0)

查看<xsl:namespace-alias ...>顶级元素的规范。我相信它会实现你想要的。