Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSLT: switch parent/child elements and sort

Status
Not open for further replies.

yoeman

Programmer
Aug 10, 2004
3
US
Newbie struggling with XSLT....

Given the below xml file, I want to create a new xml file that transposes the <town> and <company> elements in the result tree, then sorts by ascending town and company/name (alternately, I'd like to sort by ascending town and
company/name/@id). The result of my transform is the original xml file (I haven't figured out the transpose part, and the result tree is unsorted).
Any help is greatly appreciated!

XML:
<?xml version="1.0" encoding="UTF-16"?>
<?xml-stylesheet type="text/xsl" href="Sort Test.xsl" ?>
<company_data>
<company id="EFGH">
<name>EFGH Company</name>
<town>Somewhere</town>
<phone>888-888-8888</phone>
<web_address> </company>
<company id="ABCD">
<name>ABCD Company</name>
<town>Tranquil</town>
<phone>123-456-7890</phone>
<web_address> </company>
<company id="LLLL">
<name>LLLL Company</name>
<town>Sydney</town>
<phone></phone>
<web_address> </company>
</company_data>

XSLT:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="version="1.0">
<xsl:eek:utput method="xml" indent="yes" />

<xsl:template match="company_data">
<xsl:apply-templates/>
</xsl:template>

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

<xsl:template match="node() | @*">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>
 
Can you give an example of what you want the result tree to look like?

-jay
 
Sure. Basically, what I want to do is transform from a structure that has one or more <town> elements contained within a <company> element to a structure that has one or more <company> elements contained within a <town> element.
My example isn't the greatest, or truly indicative of my somewhat more complex "live" xml file, but it should serve to illustrate my problem. Also, below I have chosen to convert the text content of the <town> element to an attribute in the result tree, but it could just as easily remain an element subordinate to <town>, ex:
<town>
<name></name>
.
.
.
</town>

Thank you for any assistance you can lend!

Desired result tree:

<?xml version="1.0" encoding="UTF-16"?>
<?xml-stylesheet type="text/xsl" href="Sort Test.xsl" ?>
<company_data>
<town name="Somewhere">
<company id="EFGH">
<name>EFGH Company</name>
<phone>888-888-8888</phone>
<web_address> </company>
</town>
<town name="Tranquil">
<company id="ABCD">
<name>ABCD Company</name>
<phone>123-456-7890</phone>
<web_address> </company>
</town>
<town name="Sydney">
<company id="LLLL">
<name>LLLL Company</name>
<phone></phone>
<web_address> </company>
</town>
</company_data>
 
You could do something as simple as this:

Code:
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/">
      <xsl:apply-templates select="company_data"/>
  </xsl:template>
  <xsl:template match="company_data">
    <xsl:copy>
      <xsl:apply-templates select="company">
        <xsl:sort select="town" />
        <xsl:sort select="name" />        
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="company">
    <town name="{town}">
        <company id="{@id}">
            <name><xsl:value-of select="name"/></name>
            <phone><xsl:value-of select="phone"/></phone>
            <web_address><xsl:value-of select="web_address"/></web_address>            
        </company>
    </town>
  </xsl:template>
</xsl:stylesheet>
[/CODE

-jay
 
jaybytez,
That may have done the trick! I will need to modify and test it against my more complicated source file, but the concept seems sound. Thank you very much for the fast and very helpful reply.

I'm still struggling with XSLT syntax, even after buying 4 books!

By the way, do I need to explicitly name individual child elements and select their values, as you have done with <name>, <phone> and <web_address>, or is there a way to do a wildcard select of all child elements/attributes of the transposed parent elements?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top