You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Philip Puccio <Ph...@aexp.com> on 2001/02/27 03:08:27 UTC

xsl:copy copies attributes only sometimes

Hi all,

I've hit a perplexing problem with some simple XML and I'm hoping someone here
can easily see and explain what's going on.  I'm running with Xalan 1.2 and
Xerces 1.1.3 (for reasons of WebSphere compatibility) under VisualAge for Java
3.5.

I need to grab an element and move it a bit in the tree.  So I start with this
input XML:

           <?xml version="1.0" encoding="UTF-8"?>

           <level-0 attr1="1" attr2="2">
                     <level-1 attr1="3" attr2="4">
                               <level-2 attr1="5" attr2="6">
                                          <level-3 attr1="7" attr2="8"/>
                               </level-2>
                     </level-1>
                     <level-1 attr1="9" attr2="10">
                               <level-2 attr1="11" attr2="12">
                                          <level-3 attr1="13" attr2="14"/>
                               </level-2>
                     </level-1>
           </level-0>

What I want to do is to grab the level-3 element whose attr2 attribute is
"14" and put it into a new "moved-up" element that's the first element
within its ancestor level-1 element.  So the desired result is:

           <?xml version="1.0" encoding="UTF-8"?>

           <level-0 attr1="1" attr2="2">
                     <level-1 attr1="3" attr2="4">
                               <level-2 attr1="5" attr2="6">
                                          <level-3 attr1="7" attr2="8"/>
                               </level-2>
                     </level-1>
                     <level-1 attr1="9" attr2="10">
                               <moved-up>
                                          <level-3 attr1="13" attr2="14"/>
                               </moved-up>
                               <level-2 attr1="11" attr2="12"/>
                     </level-1>
           </level-0>

I use the following XSL:

           <?xml version="1.0"?>
           <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
           <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

           <!-- simply copy everything except the nodes specifically handled
later -->
           <xsl:template match="@*|node()">
                     <xsl:copy>
                               <xsl:apply-templates select="@*|node()"/>
                     </xsl:copy>
           </xsl:template>

           <xsl:template match="level-1[level-2/level-3/@attr2='14']">
                     <xsl:element name="{name()}">
                               <xsl:element name="moved-up">
                                          <xsl:copy-of select="level-2/level-3
[@attr2='14']"/>
                               </xsl:element>
                               <xsl:apply-templates select="@*|node()"/>
                     </xsl:element>
           </xsl:template>

           <!-- it's been moved up, make sure it doesn't also get copied in
place -->
           <xsl:template match="*[@attr2='14']"/>

           </xsl:transform>

The unexpected result follows.  The desired element has been moved to the
desired location, but the attributes for its ancestor level-1 element haven't
been copied:

           <?xml version="1.0" encoding="UTF-8"?>
           <level-0 attr1="1" attr2="2">
                     <level-1 attr1="3" attr2="4">
                               <level-2 attr1="5" attr2="6">
                                          <level-3 attr1="7" attr2="8"/>
                               </level-2>
                     </level-1>
                     <level-1>
                               <moved-up>
                                          <level-3 attr1="13" attr2="14"/>
                               </moved-up>
                               <level-2 attr1="11" attr2="12">
                               </level-2>
                     </level-1>
           </level-0>

However, if I position the <xsl:apply-templates select="@*|node()"/> to just
*before* I create the "moved-up" element, the attributes on the ancestor
level-1 element DO get copied.  Another result, of course, is that the moved-up
element is then the last element of level-1, which is not what I want:

           <?xml version="1.0" encoding="UTF-8"?>
           <level-0 attr1="1" attr2="2">
                     <level-1 attr1="3" attr2="4">
                               <level-2 attr1="5" attr2="6">
                                          <level-3 attr1="7" attr2="8"/>
                               </level-2>
                     </level-1>
                     <level-1 attr1="9" attr2="10">
                               <level-2 attr1="11" attr2="12">
                               </level-2>
                               <moved-up>
                               <level-3 attr1="13" attr2="14"/>
                          </moved-up>
                     </level-1>
           </level-0>

Any idea why this is?

Thanks very much!

.. . . Phil Puccio

P.S.  Just for grins, I tried the following (processing level-1's attributes,
then creating the "moved-up" element, then processing level-1's nodes), and it
worked, but I don't know why:

           <xsl:template match="level-1[level-2/level-3/@attr2='14']">
                     <xsl:element name="{name()}">
                               <xsl:apply-templates select="@*"/>
                               <xsl:element name="moved-up">
                                          <xsl:copy-of select="level-2/level-3
[@attr2='14']"/>
                               </xsl:element>
                               <xsl:apply-templates select="node()"/>
                     </xsl:element>
           </xsl:template>