2010-04-29 5 views
3

Я хочу сопоставить корневой элемент «FOO» и выполнить преобразование (добавить атрибут версии), оставив остальное как есть. Трансформация у меня до сих пор выглядит следующим образом:Как добавить атрибут корневого элемента в XML с помощью XSLT?

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://schemas.foo.com/fooNameSpace"> 

<xsl:template match="//FOO"> 
    <xsl:choose> 
     <xsl:when test="@version"> 
     <xsl:apply-templates select="node()|@*" /> 
     </xsl:when> 
     <xsl:otherwise> 
     <FOO> 
     <xsl:attribute name="version">1</xsl:attribute> 
     <xsl:apply-templates select="node()|@*" /> 
     </FOO> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Однако это не делает никаких преобразований. Он даже не обнаруживает элемент. Так что мне нужно сделать, добавить пространство имен для того, чтобы сделать его работу:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fd="http://schemas.foo.com/fooNameSpace"> 

<xsl:template match="//fd:FOO"> 
… 

Но это придает атрибут пространства имен на элемент FOO, а также другие элементы:

<FOO xmlns:fd="http://schemas.foo.com/fooNameSpace" version="1" id="fooid"> 
<BAR xmlns="http://schemas.foo.com/fooNameSpace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
  • Есть ли способ сказать, что элемент использует пространство имен по умолчанию?
  • Можем ли мы сопоставлять и добавлять элементы в пространство имен по умолчанию?

Вот исходный XML:

<?xml version="1.0" encoding="UTF-8"?> 
    <FOO xmlns="http://schemas.foo.com/fooNameSpace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <BAR> 
     <Attribute name="HEIGHT">2067</Attribute> 
     </BAR> 
    </FOO> 
+0

Хороший вопрос (+1). См. Мой ответ для полного решения. :) –

ответ

0

Это работает для меня, используя xsltproc/LibXSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://schemas.foo.com/fooNameSpace"> 
    <xsl:template match="/ns:FOO"> 
    <xsl:copy> 
     <xsl:if test="not(@version)"> 
     <xsl:attribute name="version">1</xsl:attribute> 
     </xsl:if> 
     <xsl:apply-templates select="node() | @*"/> 
    </xsl:copy> 
    </xsl:template> 

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

Он производит:

<?xml version="1.0"?> 
<FOO xmlns="http://schemas.foo.com/fooNameSpace" version="1"> 
    <BAR> 
     <Attribute>2067</Attribute> 
    </BAR> 
</FOO> 
+0

Downvote без предложения об улучшении? –

0

Вот одно решение действительно в духе XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fd="http://schemas.foo.com/fooNameSpace" 
    > 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

<xsl:template match="/*[self::fd:FOO and not(@version)]"> 
    <xsl:copy> 
    <xsl:attribute name="version">1</xsl:attribute> 

    <xsl:call-template name="identity"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на прилагаемом документе XML, то хотел, правильный результат получается:

<FOO xmlns="http://schemas.foo.com/fooNameSpace" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
version="1"> 
    <FOO> 
     <BAR> 
     <Attribute name="HEIGHT">2067</Attribute> 
     </BAR> 
    </FOO> 
</FOO> 
1

Вы можете указать пространство имен по умолчанию для XPath выражений, добавив атрибут xpath-default-namespace, как описано в разделе 5.2 Unprefixed QNames in Expressions and Patterns стандарта XSLT 2.0.

Пример:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xpath-default-namespace="http://schemas.foo.com/fooNameSpace"> 

    <xsl:template match="FOO[not(@version)]"> 
     <xsl:copy> 
      <xsl:attribute name="version">1</xsl:attribute> 
      <xsl:apply-templates select="node()|@*" /> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Identity template for copying everything else --> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
Смежные вопросы