2012-05-30 4 views
1

Немного сложно объяснить, что я пытаюсь сделать, поэтому я воспользуюсь упрощенным примером.Динамическое изменение пространства имен в xsl

У меня есть три XSL-шаблоны: A.xsl, B.xsl и Common.xsl

Оба A.xsl и B.xsl используют "XSL: включить" включить 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> 

Итак, А и В выглядят по-другому, они используют один и тот же префикс пространства имен (tns), но пространства имен имеют разные значения. A и B включают Common.xsl, который также использует пространство имен tns.

Другими словами, я хочу, чтобы пространство имен tns в Common.xsl принимало значение «вызывающего», то есть A или B, xsl-файла.

Однако это не работает при использовании XslCompiledTransform, он жалуется, что tns является незаявленным пространством имен, когда в Common.xsl. Если я объявляю пространство имен tns в Common.xsl, мне нужно использовать либо http://MyNamespaceForA, либо http://MyNamespaceForB.

Скажем, я объявляю tns как http://MyNamespaceForB в Common.xsl. Теперь, когда я использую A.xsl, будут конфликтующие значения пространств имен tns. Эффект будет заключаться в том, что XML-элементы, сгенерированные Common.xsl, будут иметь явное значение пространства имен http://MyNamespaceForB. Конечно, это не сработает.

Надеюсь, что я несколько ясно, что я пытаюсь сделать. Короче говоря, я хочу, чтобы «вызывающий» xsl-файл диктует значение пространства имен в включенном xsl-файле.

Любые идеи? /Fredrik

ответ

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> 
Смежные вопросы