[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

trivial docbook helper script - useful?



I wrote this to automatically index various programming language
constructs, similar to the way makeinfo does (with @deftypefunc and
similar commands).  It snarfs the content of elements like
<function>foo</function> and prints a list of <indexterm>'s.

#! /usr/bin/perl -w
# specindex.pl - a simple index autogenerator

use SGMLS;

our $VERSION = '$Id: specindex.pl,v 1.3 2003/04/01 01:06:36 itz Exp $';
our $parse = SGMLS->new(STDIN);
our %index_elements =
(
 function   => 'function',
 classname  => 'class',
 structname => 'struct',
 type       => 'type',
 varname    => 'variable',
 constant   => 'constant',
 command    => 'program',
 );

our %section_elements =
    map {$_, 1} qw(preface chapter appendix glossary bibliography
                   sect1 sect2 sect3 sect4 section simplesect glossdiv bibliodiv);
our $content = '';
our %indexmap = ( );

sub find_target {
    my $element = $_[0];

  PARENT:
    while(1) {
        my $parent = $element->parent;
        (ref $parent) eq 'SGMLS_Element' or return undef;
        my $name = $parent->name;
        $element = $parent, next PARENT
            unless $section_elements{$name} &&
            ref $parent->attribute('id') eq 'SGMLS_Attribute';
        my $id = $parent->attribute('id')->value;
        $element = $parent, next PARENT unless $id;
        return $id;
    }
}

 EVENT:
    while (1) {
        
        my $event = $parse->next_event;
        (ref $event) eq SGMLS_Event or last EVENT;
        for ($event->type) {
            /^conforming/		and last EVENT;
            /^start_element/		and do {
                my $element = $event->data;    # An object of class SGMLS_Element
                my $name = $element->name;
                $content = '' if $index_elements{$name};
                next EVENT;
            };
            /^end_element/			and do {
                my $element = $event->data;    # An object of class SGMLS_Element
                my $name = $element->name;
                if ($index_elements{$name}) {
                    my $id = &find_target($element);
                    defined $id or next EVENT;
                    $indexmap{"$content ($index_elements{$name})"}->{$id} = 1;
                }
                next EVENT;
            };
            /^cdata/			and do {
                my $cdata = $event->data;      # A string
                my $element = $event->element;
                my $name = $element->name;
                $content .= $cdata if $index_elements{$name};
                next EVENT;
            };
        }
    }

our $idgen = 1;

foreach my $entry (sort(keys %indexmap)) {
    print '<indexterm id="idx:ID', $idgen++,'" zone="', join(' ',keys %{$indexmap{$entry}});
    print '"><primary>', $entry, '</primary></indexterm>', "\n";
}

___END___

Use like this:

$(NSGMLS) $(NSGMLSFLAGS) xml.dcl foo.xml | specindex.pl > idxterms.xml

then declare an external entity for idxterms.xml, call it out at a
strategic point in the document (i.e. anywhere the DTD allows it), and
let the stylesheet do its indexing magic.

If anyone thinks this has potential for wider use, let me know.

-- 
Ian Zimmerman, Oakland, California, U.S.A. 
if (sizeof(signed) > sizeof(unsigned) + 4) { delete this; }
GPG: 433BA087  9C0F 194F 203A 63F7 B1B8  6E5A 8CA3 27DB 433B A087



Reply to: