如何在样式表中发出xsi:type属性?

时间:2012-10-23 19:17:16

标签: xml xslt xsitype

我有一个XSLT样式表需要发出一个看起来像这样的XML片段(为简洁起见,“......”位被省略):

<MyOuterType xmlns:xsi="..." xsi:type="foo:MyInnerType" xmlns:foo="..."/>

样式表如下所示:

<xsl:stylesheet xmlns:foo="..." xmlns:xsi="...">
  ...
  <xsl:template match="...">
    <xsl:element name="MyOuterType">
      <xsl:attribute name="xsi:type">foo:MyInnerType</xsl:attribute>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

XSLT处理器的输出如下所示:

<MyOuterType xmlns:xsi="..." xsi:type="foo:MyInnerType"/>

换句话说,它缺少xmlns:foo声明。实际上,尽管声明在样式表中声明,但声明在发出的XML中完全不存在。当我需要对发出的XML进行反序列化时,这会让事情变得混乱。

如何让我的xmlns:foo出现在发出的XML中?处理器实现了XSLT 1.0。

1 个答案:

答案 0 :(得分:0)

这取决于您是否知道要静态生成的命名空间,或者它是否基于输入文档中的信息。

如果你静态地知道它,只需使用文字结果元素而不是xsl:element:

<MyOuterType xsi:type="foo:MyInnerType" xmlns:foo="....."/>

如果这是一个动态决定,那就有点复杂了。 XSLT 2.0有一个xsl:namespace指令来生成命名空间,其方式与xsl:attribute生成属性的方式非常相似。在XSLT 1.0中,技巧是创建一个包含所需命名空间的元素,然后使用xsl:copy复制命名空间节点:

<xsl:variable name="dummy">
  <xsl:element name="foo:dummy" namespace="{$param}"/>
</xsl:variable>
<MyOuterType xsi:type="foo:MyInnerType">
  <xsl:copy-of select="exsl:node-set($dummy)/*/namespace::foo"/>
</MyOuterType>

不幸的是,有一个或两个不太完整的XSLT-1.0处理器没有正确实现命名空间节点,所以请谨慎。