2

使用 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',只有'一种'。将上面的行更改<!-- 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:”等创建输入文档。我希望能够使用“友好”命名空间前缀显示这些前缀。

更新:范围内前缀()行为由静态已知命名空间的定义解释

4

3 回答 3

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>
于 2010-07-22T01:50:07.250 回答
1

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

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

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

于 2010-07-21T21:42:12.803 回答
0

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

于 2010-07-21T21:34:41.733 回答