OOP Question was: (Re: Phoenix.pm: Next meeting)

Douglas E. Miles doug.miles at bpxinternet.com
Sat Feb 5 17:14:13 CST 2000


"Douglas E. Miles" wrote:
> 
> On Feb 4,  3:06pm, Douglas E. Miles wrote:
> 
> > I don't really have a topic, but I do have an OO quandry that I could
> > use some help with.  Anybody interested?  It's a little too complicated
> > to explain here.
> 
> Why don't you explain it here?  Not all of us come to the meetings.

Mainly because I thought it might be too complicated to try to explain
well in an email, and because it would take quite a bit of time.  :)
However, I'll make an attempt.

> Also, I have found that sometimes explaining a problem in writing
> helps clarify the problem (in the writer's mind) and often a solution
> will occur to you in the process.

I agree with this wholeheartedly.  I often use this technique (usually
verbally though) to solve problems.

Without further ado...

I am using XML::Parser (in the object style) to parse XML documents to a
database.  When you create a new XML::Parser object, you can specify a
package (class) that the objects in the object tree get blessed into. 
If you specify the package to be "XML" and if you have XML like this:

<doc>
  <title>title</title>
  <para>blah, blah, blah</para>
</doc>

the doc element gets blessed into XML::doc.  The character data gets
blessed into XML::Characters.  This occurs by just appending the two
together (yes, I did use the Source :) ).  However, the packages don't
appear to be declare anywhere (I don't know if this makes a difference
or not).  My problem is that I want to have all of the XML::* classes to
inherit from the XML class.  I did something like this (full source
later):

package XML;

<methods here>

package XML::title

@ISA = ('XML');

package XML::Characters

@ISA = ('XML');

etc.

However, perl could not find the methods that I was trying to inherit
from XML.  Also, I tried dumping the symbol table (I haven't done this
before, so I may have screwed up), and found the XML package, but not
any of the XML::* packages.  I have this working now by creating the
method in each of XML::* which calls the same method in XML.  Not as
clean as I would like.  Eventually, I want to loop through XML::* in the
symbol table, and tell each one to inherit from XML.  The reason I want
to do all of this, is that I want to be able to process XML documents
without knowing all of the element names ahead of time.  DISCLAIMER this
source is highly experimental, ugly, partially functional, and sub
optimal.  I'm not responsible if it makes your hair fall out, your nose
bleed, or causes madness. :)

#!/usr/bin/perl

use XML::Parser;
use Data::Dumper;

require 'xml_parser.cfg';
require 'dba.pl';

my $xml_document = shift;

my $parser = new XML::Parser(Style => 'Objects',
                             Pkg   => 'XML_ObjTree');

my $object_tree = $parser->parsefile($xml_document);
print "$object_tree\n";

foreach $symname (sort(keys(%main::)))
{

  local *sym = $main::{$symname};
  print "\$$symname is defined\n" if defined $sym;
  print "\@$symname is defined\n" if defined @sym;
  print "\%$symname is defined\n" if defined %sym;
  print "\&$symname is defined\n" if defined &sym;

}

$object_tree->[0]->traverse();
$object_tree->[0]->dump_tree();

package XML_ObjTree;

# Initialize global node counter.
$Node_Counter = 0;

sub traverse
{

  my $self = shift;

  # Number the left side of the node.
  $self->{left_node_count} = ++$Node_Counter;

  local ($index);

  # Loop through all kids.
  foreach $index (0..$#{$self->{Kids}})
  {

    # Recurse kid.
    $self->{Kids}->[$index]->traverse();

  }

  # Done with branch; number right side of the node.
  $self->{right_node_count} = ++$Node_Counter;

  XML_ObjTree::insert_element($self);

} # END: traverse

sub insert_element
{

  my $self = shift;

  # Get the element from the class name.
  my $element = (reverse(split(/::/, ref($self))))[0];

print "\$element: $element\n";
  my @fields = (1, $element, 1, $self->{left_node_count},
                $self->{right_node_count});

  my $fields = join(',', map("\'$_\'", @fields));

printf($::Element_Insert, $fields);
#  SQL_Insert(sprintf($Event_Insert, $values));

} # END: insert_element

sub dump_tree
{

  my $self = shift;
  print main::Dumper($self);

}

package XML_ObjTree::report;

@ISA = ('XML_ObjTree');

sub traverse
{

  my $self = shift;
  XML_ObjTree::traverse($self);

}

sub dump_tree
{

  my $self = shift;
  print main::Dumper($self);

}

package XML_ObjTree::title;

@ISA = ('XML_ObjTree');

sub traverse
{

  my $self = shift;
  XML_ObjTree::traverse($self);

}

sub dump_tree
{

  my $self = shift;
  print main::Dumper($self);

}

package XML_ObjTree::Characters;

@ISA = ('XML_ObjTree');

sub traverse
{

  my $self = shift;
  XML_ObjTree::traverse($self);

}

sub dump_tree
{

  my $self = shift;
  print main::Dumper($self);

}

####################################

Here is the XML:

<report><title level="1">title1</title><title level="2"
foo="bar">title2</title></report>

If Netscape screws up the formatting here, the above should all be on
one line, so that no extra Characters objects are created for useless
white space.  Enjoy!

-- 
"We've heard that a million monkeys at a million keyboards could 
produce the Complete Works of Shakespeare; now, thanks to the 
Internet, we know this is not true."  
    --Robert Wilensky



More information about the Phoenix-pm mailing list