I think it would be better if you used some of the XML modules out there. Parsing XML by hand is (nearly) always the wrong choice.
For example, I wrote a simple XSLT solution. It's not Perl, and it's not pretty, but it seems to work.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tr
+ansform">
<xsl:key name="spec_id" match="species" use="@id"/>
<xsl:key name="block_id" match="block" use="concat(../@id,@id)"/>
<xsl:template match="/root">
<!-- get the first species for each id -->
<xsl:for-each select="/root/species[count(.|key('spec_id',@id)[1])=1]
+">
<xsl:variable name="s_id" select="@id"/>
<species>
<xsl:attribute name="id"><xsl:value-of select="$s_id"/></xsl:attrib
+ute>
<!-- get the first block for each id -->
<xsl:for-each select="/root/species[@id=$s_id]/block[count(.|key('b
+lock_id',concat($s_id,@id))[1])=1]">
<xsl:variable name="b_id" select="@id"/>
<block>
<xsl:attribute name="id"><xsl:value-of select="$b_id"/></xsl:attr
+ibute>
<!-- for each block, get contents -->
<xsl:for-each select="/root/species[@id=$s_id]/block[@id=$b_id]/n
+ode()">
<xsl:copy/>
</xsl:for-each>
</block>
</xsl:for-each>
</species>
</xsl:for-each>
</xsl:template>
<xsl:template match="block">
</xsl:template>
</xsl:stylesheet>
This XSLT program transforms this:
<?xml version="1.0" ?>
<root>
<species id="1">
<block id="1">
stuff a
</block>
</species>
<species id="1">
<block id="1">
stuff b
</block>
</species>
<species id="1">
<block id="2">
stuff c
</block>
</species>
<species id="1">
<block id="2">
stuff d
</block>
</species>
<species id="2">
<block id="1">
stuff e
</block>
</species>
<species id="2">
<block id="1">
stuff f
</block>
</species>
<species id="2">
<block id="2">
stuff g
</block>
</species>
<species id="2">
<block id="2">
stuff h
</block>
</species>
</root>
into this:
<?xml version="1.0"?>
<species id="1"><block id="1">
stuff a
stuff b
</block><block id="2">
stuff c
stuff d
</block></species><species id="2"><block id="1">
stuff e
stuff f
</block><block id="2">
stuff g
stuff h
</block></species>
To extend it, you have to:
- Add more keys
- Nest other for-each blocks
--
dakkar - Mobilis in mobile