title: XSL Transform Across Namespaces
body: <p>I have XML that looks something like this:</p>
  
  <pre><code>&lt;Root xmlns="http://widgetspecA.com/ns"&gt;
    ...any...
    &lt;WidgetBox&gt;
      &lt;A/&gt;
      &lt;B/&gt;
      &lt;SmallWidget&gt; &lt;!-- minOccurs='0' --&gt;
        ...any...
      &lt;/SmallWidget&gt;
      &lt;Widgets&gt; &lt;!-- minOccurs='0' --&gt;
        ...any...
      &lt;/Widgets&gt;
      ...any...
    &lt;/WidgetBox&gt;
    ...any...
  &lt;/Root&gt;
  </code></pre>
  
  <p>and I want to transform it into this:</p>
  
  <pre><code>&lt;Root xmlns="http://widgetspecB/ns"&gt;
    ...any...
    &lt;WidgetBox&gt;
      &lt;A/&gt;
      &lt;B/&gt;
      &lt;Widgets&gt;
        &lt;Atom&gt;
          ...any...
        &lt;/Atom&gt;
        &lt;Molecule&gt;
          ...any...
        &lt;/Molecule&gt;
      &lt;/Widgets&gt;
      ...any...
    &lt;/WidgetBox&gt;
    ...any...
  &lt;/Root&gt;
  </code></pre>
  
  <p>In other words:</p>
  
  <p><code>&lt;SmallWidget&gt;</code> in specA means the same thing as <code>&lt;Atom&gt;</code> in specB, so just rename the element.</p>
  
  <p><code>&lt;Widgets&gt;</code> in specA means the same thing as <code>&lt;Molecule&gt;</code> in specB, so just rename the  element.</p>
  
  <p>Wrap <code>&lt;Atom&gt;</code> and <code>&lt;Molecule&gt;</code> in an element named <code>&lt;Widgets&gt;</code>, which means something different from specA's <code>&lt;Widgets&gt;</code>.</p>
  
  <p>Everything else gets copied as is, but in the new namespace.</p>
  
  <p>What would the XSLT be for this?</p>
  
  <p>SOLUTION?: In the end I went with this:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:old="http://widgetspecA.com/ns"
      xmlns="http://widgetspecB.com/ns"
      exclude-result-prefixes="old"&gt;
  
    &lt;xsl:output method="xml"/&gt;
  
    &lt;xsl:template match="*"&gt;
      &lt;xsl:element name="{name()}"&gt;
        &lt;xsl:copy-of select="@*"/&gt;
        &lt;xsl:apply-templates/&gt;
      &lt;/xsl:element&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match="old:SmallWidget" mode="single"&gt;
      &lt;Atom&gt;
        &lt;xsl:apply-templates/&gt;
      &lt;/Atom&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match="old:Widgets" mode="single"&gt;
        &lt;Molecule&gt;
          &lt;xsl:apply-templates/&gt;
        &lt;/Molecule&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match="old:SmallWidget[following-sibling::old:Widgets]"&gt;
        &lt;Widgets&gt;
         &lt;xsl:apply-templates select="self::node()" mode="single"/&gt;
         &lt;xsl:apply-templates select="following-sibling::old:Widgets" mode="single"/&gt;
        &lt;/Widgets&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match="old:Widgets[preceding-sibling::old:SmallWidget]"/&gt;
  
    &lt;xsl:template match="old:SmallWidget[not(following-sibling::old:Widgets)]"&gt;
        &lt;Widgets&gt;
         &lt;xsl:apply-templates select="self::node()" mode="single"/&gt;
        &lt;/Widgets&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match="old:Widgets[not(preceding-sibling::old:SmallWidget)]"&gt;
        &lt;Widgets&gt;
         &lt;xsl:apply-templates select="self::node()" mode="single"/&gt;
        &lt;/Widgets&gt;
    &lt;/xsl:template&gt;
  
  &lt;/xsl:stylesheet&gt;
  </code></pre>