2013-04-22 2 views
3

Вот мой входного XML документ:XSLT 2.0 - изменение имена без сохранения существующих привязок префикса

<test xmlns="http://www.example.com/v1"> 
    <qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue> 
</test> 

Я хочу использовать XSLT (2.0), чтобы изменить пространство имен этого документа v2, т.е. желаемого результата:

<test xmlns="http://www.example.com/v2"> 
    <qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue> 
</test> 

Я пытаюсь использовать эту таблицу стилей:

<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
    xmlns:previous='http://www.example.com/v1'> 
    <xsl:output encoding='UTF-8' indent='yes' method='xml'/> 
    <!-- Identity transform --> 
    <xsl:template match='@*|node()'> 
    <xsl:copy> 
     <xsl:apply-templates select='@*|node()'/> 
    </xsl:copy> 
    </xsl:template> 
    <!-- Previous namespace -> current. No other changes required. --> 
    <xsl:template match='previous:*'> 
    <xsl:element name='{local-name()}' namespace='http://www.example.com/v2'> 
     <xsl:apply-templates select='@* | node()' /> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

к сожалению, выход получается как:

<test xmlns="http://www.example.com/v2"> 
    <qnameValue>foo:bar</qnameValue> 
</test> 

То есть ключевое связывание пространства имен на qnameValue прошло. Есть ли способ заставить копию всех привязок пространства имен к выходу?

ответ

5

Это должно сделать это, и XSLT 1.0 совместимы:

<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
    xmlns:previous='http://www.example.com/v1'> 
    <xsl:output encoding='UTF-8' indent='yes' method='xml'/> 
    <!-- Identity transform --> 
    <xsl:template match='@*|node()'> 
    <xsl:copy> 
     <xsl:apply-templates select='@*|node()'/> 
    </xsl:copy> 
    </xsl:template> 
    <!-- Previous namespace -> current. No other changes required. --> 
    <xsl:template match='previous:*'> 
    <xsl:element name='{local-name()}' namespace='http://www.example.com/v2'> 
     <xsl:copy-of select='namespace::*[not(. = namespace-uri(current()))]' /> 
     <xsl:apply-templates select='@* | node()' /> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

При запуске на своем входе пробы, результат:

<test xmlns="http://www.example.com/v2"> 
    <qnameValue xmlns:foo="http://foo.example.com/">foo:bar</qnameValue> 
</test> 

Это аналогичный подход, который может быть небольшой бит более эффективен, сохраняя старый uri в переменной и получая его оттуда:

<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
    xmlns:previous='http://www.example.com/v1'> 
    <xsl:output encoding='UTF-8' indent='yes' method='xml'/> 
    <xsl:variable name='oldUri' select='namespace-uri((//previous:*)[1])' /> 

    <!-- Identity transform --> 
    <xsl:template match='@*|node()'> 
    <xsl:copy> 
     <xsl:apply-templates select='@*|node()'/> 
    </xsl:copy> 
    </xsl:template> 
    <!-- Previous namespace -> current. No other changes required. --> 
    <xsl:template match='previous:*'> 
    <xsl:element name='{local-name()}' namespace='http://www.example.com/v2'> 
     <xsl:copy-of select='namespace::*[not(. = $oldUri)]' /> 
     <xsl:apply-templates select='@* | node()' /> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Именно то, что я искал. Благодаря! –

Смежные вопросы