3

我正在使用 Microsoft 的 XSLT 处理器(仅限 1.0)

XML 开场白:

<?xml version="1.0" encoding="utf-8"?>
<Header xmlns="http:\\OldNameSpace.com">
    <Detail>

使用以下 XSLT 模板来获取<Header>我的文档的元素并更改其名称空间。

<xsl:template match="*">
    <xsl:element name="{name()}" xmlns="http:\\NewNameSpace.com"> 
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

变成<Header xmlns="http:\\OldNameSpace.com">_<Header xmlns="http:\\NewNameSpace.com">

但是,我现在需要为此添加第二个命名空间,以便获得以下输出:

<Header xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

我试过使用:

<xsl:template match="*">
    <xsl:element name="{name()}" xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

但是,我仍然只能得到与原始 XSLT 模板相同的输出。

谁能告诉我这是为什么?

4

3 回答 3

5

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:old="http:\\OldNameSpace.com"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  exclude-result-prefixes="old xsi">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNewNamespace" select="'http:\\NewNameSpace.com'"/>

 <xsl:variable name="vXsi" select="document('')/*/namespace::*[name()='xsi']"/>

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

    <xsl:template match="old:*">
        <xsl:element name="{local-name()}" namespace="{$pNewNamespace}">
          <xsl:copy-of select="$vXsi"/>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

当应用于以下 XML 文档时

<Header xmlns="http:\\OldNameSpace.com">
    <Detail/>
</Header>

产生(我猜是)想要的正确结果

<Header xmlns="http:\\NewNameSpace.com"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Detail/>
</Header>
于 2012-04-11T12:14:26.890 回答
2

xsl:element(与文字结果元素不同)不会所有范围内的名称空间复制到结果中,而只是将元素名称所需的名称空间 9 隐含地从其名称中或使用名称空间参数指定)。

xslt2 为这种情况添加了一个 xsl:namespace 指令,但在 xslt1 中最简单的做法是

在哪里

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

在祖先的某个地方(例如在 xsl:stylesheet 上。)

这将在输出中添加虚假信息xsi:tmp="",但也会添加名称空间声明,如果您实际上需要此名称空间中的属性,例如xsi:type在上面使用它而不是 tmp ,您就完成了。如果您不介意 xsi 命名空间中额外的、可能无效的属性,那么您就完成了。否则在变量中执行上述操作,然后用于msxsl:node-set查询变量并删除虚假的额外属性。

于 2012-04-11T08:59:07.750 回答
2

如果您静态地知道要生成什么名称空间,那么在 XSLT 1.0 中执行此操作的最简单方法是使用 xsl:copy-of。创建一个源文件<dummy xmlns:xsi="http://whatever"/>,然后<xsl:copy-of select="document('dummy.xml')/*/namespace::xsi"/>在你的调用里面做xsl:element

于 2012-04-11T11:37:44.473 回答