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->Reeds</cat>
<cat catid="98">PWC->Reeds->Demo</cat>
<cat catid="99">PWC->Reeds->Demo->Pop</cat>
<cat catid="41">PWC->Intake Grates</cat>
<cat catid="24">Truck</cat>
<cat catid="44">Truck->Accessories</cat>
<cat catid="22">Snowmobile</cat>
<cat catid="30">Snowmobile->Parts</cat>
<cat catid="31">Snowmobile->Accessories</cat>
<cat catid="34">Snowmobile->Accessories->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"