XSLT中的别名前缀(不是命名空间)

时间:2014-09-13 14:22:40

标签: xml xslt transformation xml-namespaces

我想在样式表本身的前缀中更改输出中的前缀。

XSLT文件:

<stylesheet version="1.0" xmlns:a="nsA">
 <template match="/">
  <a:out/>
 </template>
</stylesheet>

我得到了什么:

<a:out xmlns:a="nsA" />

我想要的是什么:

<b:out xmlns:b="nsA" />

请注意,我只想更改前缀,而不是名称空间。元命名空间别名将仅转换命名空间,保留前缀完整。

如果可以完全删除前缀,则获得积分:

<out xmlns="nsA" />

请注意,XSLT元素没有前缀,输出元素是前缀。它必须保持这样。我知道问题可以通过前缀XSLT和取消前缀输出元素来解决,但它不是一个选项。要输出的元素必须具有样式表中提供的前缀,只有在输出时才应该更改。

4 个答案:

答案 0 :(得分:5)

  

我得到了什么:

     

<a:out xmlns:a="nsA" />

不,那不是你得到的 - 至少不是你应该得到的。使用一个像样的XSLT处理器,您将收到一个错误,告诉您该文档不是有效的样式表。

  

请注意,XSLT元素没有前缀

不确定为什么你会想要它(它类似于在腿上射击自己)但是如果你坚持,你可以为样式表定义默认命名空间,并使用未加前缀的XSLT元素,例如:

<stylesheet version="1.0" 
xmlns="http://www.w3.org/1999/XSL/Transform">

<template match="/">
    <!-- ... -->
</template>

</stylesheet>

但是,在这种情况下,非XSLT元素必须是前缀或明确指定名称空间。

  

如果可以完全删除前缀,则获得积分:

     

<out xmlns="nsA" />

如果这就是你想要的,为什么不写下这个呢?

其中一个:

<stylesheet version="1.0" 
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:a="nsA"
exclude-result-prefixes="a">

<template match="/">
    <element name="out" namespace="nsA"/>
</template>

</stylesheet>

或简单地说:

<stylesheet version="1.0" 
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:a="nsA"
exclude-result-prefixes="a">

<template match="/">
    <out xmlns="nsA"/>
</template>

</stylesheet>

将产生:

<?xml version="1.0" encoding="UTF-8"?>
<out xmlns="nsA"/>

请注意,xmlns:a="nsA"声明只是为了解决源XML文档中恰好位于相同的&#34; nsA&#34;中的元素。命名空间。否则它完全是多余的。

答案 1 :(得分:2)

XSLT 1.0保留了实现定义的前缀选择; XSLT 2.0强制要求对于文字结果元素,输出中的前缀将与样式表中的前缀相同。所以你被软管了。

如果放宽约束,当然有很多方法可以解决您的问题。一个有趣的解决方案是在执行之前转换样式表;更加行人的方法是将输出转换为后处理步骤。

答案 2 :(得分:1)

也许是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:a="nsA"
    xmlns:b="nsA">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

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

</xsl:stylesheet>

答案 3 :(得分:1)

你显然在限制你如何被允许编写XSLT但是决定让他们对我们保密(感谢你),所以我们只能猜测什么会符合你的要求。

如果:

  • 您的XSLT引擎支持各种node-set()函数
  • 您可以修改与文档根目录匹配的模板(如果没有,则添加一个)
  • 您可以添加新模板

然后以下内容适用于您的请求的“奖金”版本。

添加以下模板(如果您已经有一个与文档根匹配的模板,请将此版本中的<apply-templates />替换为原始模板的内容,并删除原始模板):

<template match="/">
  <variable name="result">
    <apply-templates />
  </variable>
  <!-- If you're using something other than exslt to get the node-set
       function, then use the namespace for that instead. -->
  <apply-templates select="exslt:node-set($result)" 
                   mode="fixupNamespace" 
                   xmlns:exslt="http://exslt.org/common" />
</template>

添加以下三个模板:

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

<template match="*" mode="fixupNamespace">
  <element name="{name()}" namespace="{namespace-uri()}">
    <apply-templates select="node() | @*" mode="fixupNamespace" />
  </element>
</template>

<template match="a:*" mode="fixupNamespace">
  <element name="{local-name()}" namespace="nsA">
    <apply-templates select="node() | @*" mode="fixupNamespace" />
  </element>
</template>

你应该全力以赴。