在xsl中动态更改名称空间

时间:2012-05-30 17:18:42

标签: xslt xslcompiledtransform

解释我想要做的事情有点棘手,所以我将使用一个过于简化的例子。

我有三个Xsl-templates: A.xsl,B.xsl和Common.xsl

A.xsl和B.xsl都使用“xsl:include”来包含Common.xsl。 A.xsl看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tns="http://MyNamespaceForA" >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:include href="Common.xslt"/>
    <xsl:template match="/">
        <tns:RootA>
            <xsl:apply-templates select="Root" />
        </tns:RootA>
    </xsl:template>
</xsl:stylesheet>

B.xls看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tns="http://MyNamespaceForB" >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:include href="Common.xslt"/>
    <xsl:template match="/">
        <tns:RootB>
            <xsl:apply-templates select="Root" />
        </tns:RootB>
    </xsl:template>
</xsl:stylesheet>

最后,Common.xls看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="Root">
        <tns:Element>
            <tns:SubElement>
            </tns:SubElement>
        </tns:Element>
    </xsl:template>
</xsl:stylesheet>

因此,A和B看起来不同,它们使用相同的名称空间前缀(tns),但名称空间具有不同的值。 A和B包括Common.xsl,它也使用tns命名空间。

换句话说,我希望Common.xsl中的tns名称空间取“调用”的值,即A或B,xsl文件。

但是,这在使用XslCompiledTransform时不起作用,它抱怨在Common.xsl中tns是未声明的命名空间。如果我在Common.xsl中声明tns名称空间,我需要使用http://MyNamespaceForAhttp://MyNamespaceForB

假设我在Common.xsl中将tns声明为http://MyNamespaceForB。现在,当我使用A.xsl时,tns命名空间的值会有冲突。结果是,Common.xsl生成的XML元素将具有http://MyNamespaceForB的显式名称空间值。当然,那不行。

希望我有点清楚我想要做什么。简而言之,我希望“调用”xsl-file在包含的xsl文件中指定命名空间的值。

有什么想法吗? / Fredrik

1 个答案:

答案 0 :(得分:1)

如果在Common.xslt中使用直接命名空间,则必须在同一文件中声明命名空间,否则它将不是有效的XML - XSLT处理器无法加载它。

解决方案是使用xsl:element创建元素并使用变量作为目标命名空间

<强> A.xslt

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:variable name="targetNS" select="'http://MyNamespaceForA'"/>

  <xsl:include href="common.xslt"/>

  <xsl:template match="/">
    <xsl:element name="RootA" namespace="{$targetNS}">
      <xsl:apply-templates select="Root"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

<强> Common.xslt:

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="Root">
    <xsl:element name="Element" namespace="{$targetNS}">
      <xsl:element name="SubElement" namespace="{$targetNS}">
      </xsl:element>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>