3

I want to match a root Element “FOO” and perform the transformation (add a version attribute) to it leaving the rest as it is. The Transformation I have so far looks like this:

<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>

However this does not perform any transformation. It doesn't even detect the element. So I need to do add the namespace in order to make it work:

<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">
 …

But this attaches a namespace attribute to the FOO element as well as other elements:

<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">
  • Is there a way to say that the element is using the default namespace?
  • Can we match and add elements in the default name space?

Here is the original 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>
1
  • Good Question (+1). See my answer for a complete solution. :) Commented Apr 29, 2010 at 4:58

3 Answers 3

1

You can specify the default namespace for XPath expressions by adding the attribute xpath-default-namespace, as described in the section 5.2 Unprefixed QNames in Expressions and Patterns of the XSLT 2.0 standard.

Example:

<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>
Sign up to request clarification or add additional context in comments.

Comments

0

This works for me using 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>

It produces:

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

Comments

0

Here is one solution truly in the spirit of 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>

When this transformation is applied on the provided XML document, the wanted, correct result is produced:

<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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.