1*4176Stz204579# 2*4176Stz204579# CDDL HEADER START 3*4176Stz204579# 4*4176Stz204579# The contents of this file are subject to the terms of the 5*4176Stz204579# Common Development and Distribution License (the "License"). 6*4176Stz204579# You may not use this file except in compliance with the License. 7*4176Stz204579# 8*4176Stz204579# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4176Stz204579# or http://www.opensolaris.org/os/licensing. 10*4176Stz204579# See the License for the specific language governing permissions 11*4176Stz204579# and limitations under the License. 12*4176Stz204579# 13*4176Stz204579# When distributing Covered Code, include this CDDL HEADER in each 14*4176Stz204579# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4176Stz204579# If applicable, add the following below this CDDL HEADER, with the 16*4176Stz204579# fields enclosed by brackets "[]" replaced with your own identifying 17*4176Stz204579# information: Portions Copyright [yyyy] [name of copyright owner] 18*4176Stz204579# 19*4176Stz204579# CDDL HEADER END 20*4176Stz204579# 21*4176Stz204579# 22*4176Stz204579# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*4176Stz204579# Use is subject to license terms. 24*4176Stz204579# 25*4176Stz204579# ident "%Z%%M% %I% %E% SMI" 26*4176Stz204579# 27*4176Stz204579 28*4176Stz204579# <t> xmlHandlers -- package for generating a tree from an XML doc 29*4176Stz204579 30*4176Stz204579use XML::Parser; 31*4176Stz204579 32*4176Stz204579package xmlHandlers; 33*4176Stz204579 34*4176Stz204579$level = -1; 35*4176Stz204579 36*4176Stz204579%endCallback = (); 37*4176Stz204579%startCallback = (); 38*4176Stz204579 39*4176Stz204579$currentObj = 0; 40*4176Stz204579@objStack = (); 41*4176Stz204579 42*4176Stz2045791; 43*4176Stz204579 44*4176Stz204579# <s> methods 45*4176Stz204579 46*4176Stz204579# pkg reference, object name (tag), optional fileName. 47*4176Stz204579 48*4176Stz204579 49*4176Stz204579sub new { 50*4176Stz204579 my $pkg = shift; 51*4176Stz204579 my $parent = shift; # ref to parent object 52*4176Stz204579 my $class = shift; # for debug use 53*4176Stz204579 54*4176Stz204579 my @kids = (); # list of child objects 55*4176Stz204579 56*4176Stz204579 push (@objStack, $parent); 57*4176Stz204579 $currentObj = bless {'class' => $class, 58*4176Stz204579 'kids' => \@kids, 59*4176Stz204579# 'parent' => $parent, 60*4176Stz204579 'attributes' => 0, 61*4176Stz204579 'content' => ''}, $pkg; 62*4176Stz204579 63*4176Stz204579 if (@_) { # if fileName passed, go! 64*4176Stz204579 die "parent for document creation must be null" 65*4176Stz204579 if ($parent); 66*4176Stz204579 executeXML (shift); 67*4176Stz204579 } 68*4176Stz204579 return $currentObj; 69*4176Stz204579} 70*4176Stz204579 71*4176Stz204579# we'll call you when your object is started 72*4176Stz204579# class method 73*4176Stz204579 74*4176Stz204579sub registerStartCallback { 75*4176Stz204579 my $objName = shift; # call me when you get <objName> 76*4176Stz204579 my $callback = shift; # \&foo($objRef, $source); 77*4176Stz204579 78*4176Stz204579 if ($startCallback{$objName}) { 79*4176Stz204579 print STDERR "duplicate callback for $objName\n"; 80*4176Stz204579 return; 81*4176Stz204579 } 82*4176Stz204579 $startCallback{$objName} = $callback; 83*4176Stz204579} 84*4176Stz204579 85*4176Stz204579 86*4176Stz204579# we'll call you when your object is completed 87*4176Stz204579# class method 88*4176Stz204579 89*4176Stz204579sub registerEndCallback { 90*4176Stz204579 my $objName = shift; # call me when you get </objName> 91*4176Stz204579 my $callback = shift; # \&foo($objRef); 92*4176Stz204579 93*4176Stz204579 if ($endCallback{$objName}) { 94*4176Stz204579 print STDERR "duplicate callback for $objName\n"; 95*4176Stz204579 return; 96*4176Stz204579 } 97*4176Stz204579 $endCallback{$objName} = $callback; 98*4176Stz204579} 99*4176Stz204579 100*4176Stz204579sub start { 101*4176Stz204579} 102*4176Stz204579sub end { 103*4176Stz204579} 104*4176Stz204579 105*4176Stz204579sub char { 106*4176Stz204579 my ($obj, $class, $string) = @_; 107*4176Stz204579 108*4176Stz204579 109*4176Stz204579} 110*4176Stz204579 111*4176Stz204579sub add { 112*4176Stz204579 my $parent = shift; 113*4176Stz204579 my $kid = shift; 114*4176Stz204579 115*4176Stz204579 push (@{$parent->{'kids'}}, $kid); 116*4176Stz204579# $kid->{'parent'} = $parent; 117*4176Stz204579} 118*4176Stz204579 119*4176Stz204579# <s> internal functions 120*4176Stz204579sub executeXML { 121*4176Stz204579 my $file = shift; 122*4176Stz204579 123*4176Stz204579 # ErrorContext - 0 don't report errors 124*4176Stz204579 # - other = number of lines to display 125*4176Stz204579 # ParseparamEnt - 1 allow parsing of dtd 126*4176Stz204579 my $parser = XML::Parser->new(ErrorContext => 1, 127*4176Stz204579 ParseParamEnt => 1); 128*4176Stz204579 129*4176Stz204579 $parser->setHandlers (Char => \&charHandler, 130*4176Stz204579 Start => \&startHandler, 131*4176Stz204579 Default => \&defaultHandler, 132*4176Stz204579 End => \&endHandler, 133*4176Stz204579 Proc => \&procHandler, 134*4176Stz204579 Comment => \&commentHandler, 135*4176Stz204579 ExternEnt => \&externalHandler); 136*4176Stz204579 137*4176Stz204579 $parser->parsefile ($file); 138*4176Stz204579} 139*4176Stz204579 140*4176Stz204579sub charHandler { 141*4176Stz204579 my ($xmlObj, $string) = @_; 142*4176Stz204579 143*4176Stz204579 chomp $string; 144*4176Stz204579 $string =~ s/^\s+//; 145*4176Stz204579 $string =~ s/\s+$//; 146*4176Stz204579 unless ($string =~ /^\s*$/) { 147*4176Stz204579# print "charHandler: $currentObj->{'class'} $string\n" if $main::debug; 148*4176Stz204579 $currentObj->{'content'} .= ' ' if ($currentObj->{'content'}); 149*4176Stz204579 $currentObj->{'content'} .= $string; 150*4176Stz204579 } 151*4176Stz204579} 152*4176Stz204579 153*4176Stz204579# create new object and attach to tree 154*4176Stz204579 155*4176Stz204579sub startHandler { 156*4176Stz204579 my $xmlObj = shift; 157*4176Stz204579 my $tag = shift; 158*4176Stz204579 159*4176Stz204579 my $obj; 160*4176Stz204579 my $parent = $currentObj; 161*4176Stz204579 162*4176Stz204579 $obj = new xmlHandlers($currentObj, $tag); 163*4176Stz204579 164*4176Stz204579 $parent->add ($obj); 165*4176Stz204579 166*4176Stz204579 $obj->processAttributes ($tag, @_); 167*4176Stz204579 168*4176Stz204579 my $functionRef; 169*4176Stz204579 if ($functionRef = $startCallback{$tag}) { 170*4176Stz204579 &$functionRef($obj, 'start'); 171*4176Stz204579 } 172*4176Stz204579 elsif ($main::debug) { 173*4176Stz204579# print "no start callback for $tag\n"; 174*4176Stz204579 } 175*4176Stz204579} 176*4176Stz204579 177*4176Stz204579sub endHandler { 178*4176Stz204579 my $xmlObj = shift; 179*4176Stz204579 my $element = shift; 180*4176Stz204579 181*4176Stz204579# print "end tag $element\n" if $main::debug; 182*4176Stz204579 183*4176Stz204579 my $functionRef; 184*4176Stz204579 if ($functionRef = $endCallback{$element}) { 185*4176Stz204579 &$functionRef($currentObj, 'end'); 186*4176Stz204579 } 187*4176Stz204579 elsif ($main::debug) { 188*4176Stz204579# print "no end callback for $element\n"; 189*4176Stz204579 } 190*4176Stz204579# $currentObj = $currentObj->{'parent'}; 191*4176Stz204579 $currentObj = pop (@objStack); 192*4176Stz204579} 193*4176Stz204579 194*4176Stz204579sub defaultHandler { 195*4176Stz204579 my ($obj, $string) = @_; 196*4176Stz204579 197*4176Stz204579 unless (!$main::debug || ($string =~ /^\s*$/)) { 198*4176Stz204579 if ($string =~ /<\?xml/) { 199*4176Stz204579 $string =~ s/<\?\S+\s+(.*)/$1/; 200*4176Stz204579 my (%parameters) = 201*4176Stz204579 parseProcInstruction ($string); 202*4176Stz204579 print STDERR "Got call to default, guessed what to do: $string\n"; 203*4176Stz204579 } 204*4176Stz204579 else { 205*4176Stz204579 print STDERR "Got call to default, didn't know what to do: $string\n"; 206*4176Stz204579 } 207*4176Stz204579 } 208*4176Stz204579} 209*4176Stz204579 210*4176Stz204579sub externalHandler { 211*4176Stz204579 my ($obj, $base, $sysid, $pubid) = @_; 212*4176Stz204579 213*4176Stz204579 $base = '' if !$base; 214*4176Stz204579 $pubid = '' if !$pubid; 215*4176Stz204579 print "external: base $base\nexternal: sysid $sysid\nexternal: pubid $pubid\n"; 216*4176Stz204579} 217*4176Stz204579 218*4176Stz204579sub commentHandler { 219*4176Stz204579 my ($obj, $element) = @_; 220*4176Stz204579 221*4176Stz204579 return unless $main::debug; 222*4176Stz204579 223*4176Stz204579 unless ($element =~ /^\s*$/) { 224*4176Stz204579 print "comment: $element\n"; 225*4176Stz204579 } 226*4176Stz204579} 227*4176Stz204579 228*4176Stz204579sub procHandler { 229*4176Stz204579 my $xmlObj = shift; 230*4176Stz204579 my $target = shift; 231*4176Stz204579 my $data = shift; 232*4176Stz204579 233*4176Stz204579 my (%parameters) = 234*4176Stz204579 parseProcInstruction ($data); 235*4176Stz204579 236*4176Stz204579 $currentObj->processAttributes ($target, $data, @_); 237*4176Stz204579} 238*4176Stz204579#<s> misc subs 239*4176Stz204579 240*4176Stz204579sub parseProcInstruction { 241*4176Stz204579 my ($args) = @_; 242*4176Stz204579 243*4176Stz204579 my (@outputArray) = (); 244*4176Stz204579 245*4176Stz204579 while ($args =~ s/([^ =]+)=\"([^"]+)\"(.*)/$3/) { # " 246*4176Stz204579 push (@outputArray, $1); 247*4176Stz204579 push (@outputArray, $2); 248*4176Stz204579 } 249*4176Stz204579 return (@outputArray); 250*4176Stz204579} 251*4176Stz204579 252*4176Stz204579sub processAttributes { 253*4176Stz204579 my $pkg = shift; 254*4176Stz204579 my ($element, %content) = @_; 255*4176Stz204579 256*4176Stz204579# print "processAttributes: element = $element\n" if $main::debug; 257*4176Stz204579 258*4176Stz204579 my $hashCount = 0; 259*4176Stz204579 foreach $attributeName (keys %content) { 260*4176Stz204579 if ($attributeName =~ /^\s*$/) { 261*4176Stz204579 delete $content{$attributeName}; # remove null entries 262*4176Stz204579 next; 263*4176Stz204579 } 264*4176Stz204579 $hashCount++; 265*4176Stz204579# print "attribute: $attributeName = $content{$attributeName}\n" 266*4176Stz204579# if $main::debug; 267*4176Stz204579 } 268*4176Stz204579 if ($hashCount && $pkg->{'attributes'}) { 269*4176Stz204579 print STDERR "need to write attribute merge logic\n"; 270*4176Stz204579 } 271*4176Stz204579 else { 272*4176Stz204579 $pkg->{'attributes'} = \%content; 273*4176Stz204579 } 274*4176Stz204579} 275*4176Stz204579 276*4176Stz204579sub getKid { 277*4176Stz204579 my $pkg = shift; 278*4176Stz204579 my $whichKid = shift; 279*4176Stz204579 280*4176Stz204579 my @kids = $pkg->getKids(); 281*4176Stz204579 my $kid; 282*4176Stz204579 foreach $kid (@kids) { 283*4176Stz204579 my $class = $kid->getClass(); 284*4176Stz204579 return $kid if $class eq $whichKid; 285*4176Stz204579 } 286*4176Stz204579 return undef; 287*4176Stz204579} 288*4176Stz204579 289*4176Stz204579sub getKids { 290*4176Stz204579 my $pkg = shift; 291*4176Stz204579 292*4176Stz204579 return @{$pkg->{'kids'}}; 293*4176Stz204579} 294*4176Stz204579 295*4176Stz204579sub getAttributes { 296*4176Stz204579 my $pkg = shift; 297*4176Stz204579 298*4176Stz204579 my $ref = $pkg->{'attributes'}; 299*4176Stz204579 300*4176Stz204579 return %$ref; 301*4176Stz204579} 302*4176Stz204579 303*4176Stz204579sub getAttr { 304*4176Stz204579 my $pkg = shift; 305*4176Stz204579 my $attr = shift; 306*4176Stz204579 307*4176Stz204579 my $ref = $pkg->{'attributes'}; 308*4176Stz204579 309*4176Stz204579 return $$ref{$attr}; 310*4176Stz204579} 311*4176Stz204579 312*4176Stz204579sub getClass { 313*4176Stz204579 my $pkg = shift; 314*4176Stz204579 315*4176Stz204579 return $pkg->{'class'}; 316*4176Stz204579} 317*4176Stz204579 318*4176Stz204579sub getContent { 319*4176Stz204579 my $pkg = shift; 320*4176Stz204579 321*4176Stz204579 my $content = $pkg->{'content'}; 322*4176Stz204579 return $content ? $content : undef; 323*4176Stz204579} 324