Trouble converting elements to attributes with XSLT

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • doozer1979
    New Member
    • Jul 2007
    • 3

    #1

    Trouble converting elements to attributes with XSLT

    Hello,

    I'm having a bit of difficulty transforming xml elements into attributes.

    I want to loop through all of the <person> elements in the document and turn all of its child elements into attributes of the person element.

    The code i am using takes the last <person> element and changes all of its elements into attributes of the root node and then removes all of child elements of every person element.


    This is the code that i am currently using.



    <xsl:styleshe et xmlns:xsl="http ://www.w3.org/1999/XSL/Transform" version="1.0" >

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="*">

    <xsl:copy>
    <xsl:for-each select="person/*">
    <xsl:attribut e name="{name(.)} ">
    <xsl:value-of select="."/>
    </xsl:attribute>
    </xsl:for-each>
    <xsl:apply-templates select="*[* or @*]|text()"/>
    </xsl:copy>
    </xsl:template>


    </xsl:stylesheet>



    the base xml document looks like this:


    <root>
    <person>
    <name>Johnny</name>
    <id>1</id>
    <departme#nt>CE O</sales>
    <reports-to>null</reports-to>
    </person>
    <person>
    <name>Madge</name>
    <id>2</id>
    <departme#nt>VP </sales>
    <reports-to>1</reports-to>
    </person>
    <person>
    <name>Pip</name>
    <id>3</id>
    <departme#nt>VP </sales>
    <reports-to>1</reports-to>
    </person>
    </root>



    after the transformation it looks like this:

    <root name="Pip" id="3" department="VP" reports-to="1">
    <person></person>
    <person></person>
    <person></person>
    </root>


    I want it to look like this:


    <root>
    <person name="Johnny" id="1" department="CEO " reports-to="Null"></person>
    <person name="Madge" id="2" department="VP" reports-to="1"></person>
    <person name="Pip" id="3" department="VP" reports-to="1"></person>
    </root>


    Your help is greatly appreciated!

    thanks.
  • jkmyoung
    Recognized Expert Top Contributor
    • Mar 2006
    • 2057

    #2
    1. The for loop is a level too high -> You get all the attributes in the first node.
    2. Your template matches root first. There's 2 possible fixes

    A. Have 1 template for root, 1 for person.
    B. Rewrite to use other generic templates.

    I like B better, so I'll show the solution for that.

    [code=xml]
    <xsl:template match="*[*]"> <!-- copy element with children -->
    <xsl:copy>
    <xsl:apply-templates/>
    </xsl:copy>
    </xsl:template>
    <xsl:template match="*[not (*)]">
    <xsl:attribut e name="{name()}" >
    <xsl:value-of select="."/>
    </xsl:attribute>
    </xsl:template>
    [/code]
    The condition [not(*)] isn't really necessary, but helps avoid confusion.

    Comment

    • doozer1979
      New Member
      • Jul 2007
      • 3

      #3
      Many thanks. Great Solution!

      Comment

      Working...