http://qs321.pair.com?node_id=185804


in reply to Looping through a subrouting

This might be totally overkill for what you're doing, but here goes. My favorite hammer is, surprise surprise, a combination of XML::LibXML and XML::LibXSLT. I've use them on a similar problem where I have a list of bookmarks in arbitrarily-deeply nested folders stored in a databse. My solution was to turn each row in the table into a single XML element, then use XSLT to transform it into HTML. I threw together the following script to generate an XML document containing the categories with the names formatted how you wanted them:

The Script

#!/usr/bin/perl -wT use strict; use XML::LibXML; use XML::LibXSLT; # Create XML Document my $dom = XML::LibXML::Document->createDocument('1.0'); my $root = $dom->createElement('categories'); $dom->setDocumentElement($root); #create cat element at append it to root for (<DATA>) { chomp; my ($id,$name,$parent) = split(/\,/,$_); my $elem = $dom->createElement('cat'); $elem->setAttribute('catid',$id); $elem->setAttribute('name',$name); $elem->setAttribute('parent',$parent); $root->appendChild($elem); } # Load and apply XSLT stylesheet my $xslt = XML::LibXSLT->new(); my $stylesheet = $xslt->parse_stylesheet_file('catnames.xsl'); my $results = $stylesheet->transform($dom); print $results->toString(1); __DATA__ 26,PWC,0 24,Truck,0 22,Snowmobile,0 30,Parts,22 31,Accessories,22 32,Off Road Bikes,0 33,Road Bikes,0 34,HJC,31 40,Reeds,26 41,Intake Grates,26 44,Accessories,24 98,Demo,40 99,Pop,98

The XSLT file:

<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi +on="1.0"> <xsl:output method="xml" version="1.0"/> <xsl:template match="/"> <catnames> <xsl:apply-templates select="//categories/cat[@parent = 0]"/> </catnames> </xsl:template> <xsl:template match="cat"> <cat> <xsl:attribute name="catid"> <xsl:value-of select="@catid"/> </xsl:attribute> <xsl:param name="parent-name"/> <xsl:if test="$parent-name"> <xsl:value-of select="$parent-name"/> <xsl:text>-></xsl:text> </xsl:if> <xsl:value-of select="@name"/> </cat> <xsl:apply-templates select="//categories/cat[@parent = current()/ +@catid]"> <xsl:with-param name="parent-name"> <xsl:if test="$parent-name"> <xsl:value-of select="$parent-name"/> <xsl:text>-></xsl:text> </xsl:if> <xsl:value-of select="@name"/> </xsl:with-param> </xsl:apply-templates> </xsl:template> </xsl:stylesheet>

The Output:

<?xml version="1.0"?> <catnames> <cat catid="26">PWC</cat> <cat catid="40">PWC-&gt;Reeds</cat> <cat catid="98">PWC-&gt;Reeds-&gt;Demo</cat> <cat catid="99">PWC-&gt;Reeds-&gt;Demo-&gt;Pop</cat> <cat catid="41">PWC-&gt;Intake Grates</cat> <cat catid="24">Truck</cat> <cat catid="44">Truck-&gt;Accessories</cat> <cat catid="22">Snowmobile</cat> <cat catid="30">Snowmobile-&gt;Parts</cat> <cat catid="31">Snowmobile-&gt;Accessories</cat> <cat catid="34">Snowmobile-&gt;Accessories-&gt;HJC</cat> <cat catid="32">Off Road Bikes</cat> <cat catid="33">Road Bikes</cat> </catnames>

I leave it as an exercise for the reader to pull the data from MySQL rather than the __DATA__ chunk. Once the new XML document is stored in $results, you could either use it as is, with a simple XPath function to lookup the category name by ID, or you could extract the category names and IDs and stick them in a hash.

-rattus, playing with his current favorite tool

__________
He seemed like such a nice guy to his neighbors / Kept to himself and never bothered them with favors
- Jefferson Airplane, "Assassin"