# # file: edgar-html.pl # desc: support to convert SEC EDGAR (edgardoc DTD format) XML documents to # HTML # # limit scope package EDGAR::HTML; use strict; use vars qw($TMPL $TMPLV2); BEGIN { my $iw_root = ($ENV{IW}) ? $ENV{IW} : "/iw"; my $edgar_root = "$iw_root/skulker/edgar/current"; # where we find our local libraries my($libdir) = "$edgar_root/lib"; if ( -d $libdir) { unshift(@INC, $libdir); } # HTML template support use HTML::Template; # text to HTML conversion use HTML::FromText; # generic edgar support data require 'edgar-lib.pl'; # EDGAR generic utility support require 'edgar-util.pl'; # EDGAR table support require 'edgar-table.pl'; } # HTML template directory my $tmpldir = "$EDGAR::lib::edgar_root/lib"; # HTML template file $TMPL = "$tmpldir/edgardoc.html.tmpl"; $TMPLV2 = "$tmpldir/edgardoc.html.2.tmpl"; # debug my $debug = 0; # # generate HTML format edgardoc # sub toHTML { my($edgardoc) = shift; my($template) = shift; my($templateVersion) = shift; my %transformer = %{$edgardoc->{'transformer'}}; my %submission = %{$edgardoc->{'submission'}}; my %parsedEdgar = %{$edgardoc->{'parsed-edgar'}}; my @stamps = @{$edgardoc->{'stamps'}}; my $tmpl = new HTML::Template(filename => $template); generateSubmissionHeader(\%submission, $tmpl, $templateVersion); generateTransformer(\%transformer, $tmpl); generateRegistrants(\@{$submission{'registrants'}}, $tmpl, $templateVersion); generateDocuments(\@{$submission{'documents'}}, \@{$parsedEdgar{'parsed-documents'}}, $tmpl, $templateVersion); generateParsedDocuments(\@{$parsedEdgar{'parsed-documents'}}, $tmpl); generateStamps(\@stamps, $tmpl); generateToC(\%submission, $tmpl); return $tmpl->output(); } # # generate Submission header info # sub generateSubmissionHeader { my($edgardoc) = shift; my($tmpl) = shift; my($version) = shift; my %submission = %{$edgardoc}; my @submission_hdr = (); my %header_tags = ( 'accession-number' => 'ACCESSION: ', 'confirming-copy' => 'CONFIRMING COPY: ', 'date-of-filing-date-change' => 'FILING DATE CHANGE: ', 'effectiveness-date' => 'EFFECTIVENESS DATE: ', 'filing-date' => 'FILING DATE: ', 'group-members' => 'GROUP MEMBERS: ', 'items' => 'ITEMS: ', 'period' => 'PERIOD: ', 'references-429' => 'REFERENCES 429: ', 'sros' => 'SROS: ', 'type' => 'TYPE: ', ); # submission header -- required fields my @fields = ('accession-number', 'type', 'filing-date'); # submission header -- optional fields my @options = ('confirming-copy', 'date-of-filing-date-change', 'effectiveness-date', 'group-members', 'items', 'period', 'references-429', 'sros' ); for (@options) { if ($submission{$_}) { push(@fields, $_); } } # change the filing date to be from YYYYMMDD to month day year $submission{'filing-date'} = &EDGAR::util::convertDate($submission{'filing-date'}); if ($version == 1) { for (my $i=0 ; $i <= $#fields ; $i+=2) { push(@submission_hdr, { 'HEADER_TAG1' => $header_tags{$fields[$i]}, 'HEADER_VAL1' => $submission{$fields[$i]}, 'HEADER_TAG2' => $header_tags{$fields[$i+1]}, 'HEADER_VAL2' => $submission{$fields[$i+1]} }); } } else { for (my $i=0 ; $i <= $#fields ; $i++) { push(@submission_hdr, { 'HEADER_TAG' => $header_tags{$fields[$i]}, 'HEADER_VAL' => $submission{$fields[$i]}, }); } } $tmpl->param('SUBMISSION_HEADER' => \@submission_hdr); # get company name my $company = ''; for (@{$submission{'registrants'}}) { my %registrant = %{$_}; my $type = $registrant{'type'}; if ($type eq 'subject-company' || $type eq 'filer') { $company = $registrant{'company-data'}{'conformed-name'}; last; } } $tmpl->param('SUBMISSION_COMPANY' => $company); $tmpl->param('SUBMISSION_TYPE' => $submission{'type'}); $tmpl->param('SUBMISSION_DATE' => $submission{'filing-date'}); # version 1 outputs these items if ($version == 1) { # document specific BUG data $tmpl->param('DOC_BUG' => 'SEC'); # ToC BUG data $tmpl->param('TOC_BUG' => 'TOC'); } # generic name for this document SPACE $tmpl->param('SPACE_NAME' => 'SEC'); } # # generate Transformer info # sub generateTransformer { my($transformer) = shift; my($tmpl) = shift; $tmpl->param('TRANSFORMER_CANONICAL' => $transformer->{'canonical'}); $tmpl->param('TRANSFORMER_CITY' => $transformer->{'city'}); $tmpl->param('TRANSFORMER_CODE' => $transformer->{'code'}); $tmpl->param('TRANSFORMER_COUNTRY' => $transformer->{'country'}); $tmpl->param('TRANSFORMER_DATE' => $transformer->{'date'}); $tmpl->param('TRANSFORMER_EMAIL' => $transformer->{'email'}); $tmpl->param('TRANSFORMER_ORG' => $transformer->{'organization'}); $tmpl->param('TRANSFORMER_REGION' => $transformer->{'region'}); $tmpl->param('TRANSFORMER_STREET' => join("
", split(/\|/, $transformer->{'street'}))); $tmpl->param('TRANSFORMER_URI' => $transformer->{'uri'}); } # # generate Registrants info # sub generateRegistrants { my($registrants) = shift; my($tmpl) = shift; my($version) = shift; my %reg_type = ( 'filed-by' => 'Filed By:', 'filer' => 'Filer:', 'reporting-owner' => 'Reporting Owner:', 'serial-company' => 'Serial Company:', 'subject-company' => 'Subject Company:', ); my %reg_tag = ( # company data 'cik' => 'CIK:', 'assigned-sic' => 'SIC:', 'irs-number' => 'IRS Number:', 'state-of-incorporation' => 'Incorporation:', 'fiscal-year-end' => 'Fiscal Year End:', # filing values 'form-type' => 'Form Type:', 'act' => 'SEC Act:', 'file-number' => 'File Number:', 'film-number' => 'Film Number:', # address 'business-address' => 'Business Address:', 'mail-address' => 'Mail Address:', 'phone' => 'Phone:', # former company data 'former-conformed-name' => 'Former Name:', 'date-changed' => 'Date Changed:', ); my %tmpl_tag = ( # company data 'conformed-name' => 'REG_FILER', 'cik' => 'REG_CIK', 'assigned-sic' => 'REG_SIC', 'irs-number' => 'REG_IRS_NUMBER', 'state-of-incorporation' => 'REG_STATE_OF_INCORPORATION', 'fiscal-year-end' => 'REG_FISCAL_YEAR_END', # filing values 'form-type' => 'REG_FORM_TYPE', 'act' => 'REG_SEC_ACT', 'file-number' => 'REG_FILE_NUMBER', 'film-number' => 'REG_FILM_NUMBER', # contact information #'contact-information' => 'REG_CONTACT_INFORMATION', # address 'business-address' => 'REG_BUSINESS_ADDRESS', 'mail-address' => 'REG_MAIL_ADDRESS', 'phone' => 'REG_PHONE', # former company data 'former-conformed-name' => 'REG_FORMER_NAME', 'date-changed' => 'REG_DATE_CHANGED', ); my @regs = (); for (@{$registrants}) { my %registrant = %{$_}; if ($version == 1) { push(@regs, { 'REGISTRANT_TAG' => $reg_type{$registrant{'type'}}, 'REGISTRANT_VAL' => $registrant{'company-data'}{'conformed-name'} },); # company data -- required fields my @fields = ('cik', 'assigned-sic'); # company data -- optional fields my @options = ('irs-number', 'state-of-incorporation', 'fiscal-year-end'); for (@options) { if ($registrant{'company-data'}{$_}) { push(@fields, $_); } } for (@fields) { my $val = $registrant{'company-data'}{$_}; # rewrite SIC text if ($_ eq 'assigned-sic' && $val) { my($sic_html) = qq|$val"; $val = "$EDGAR::lib::sic_codes{$val} [$sic_html]"; $val = EDGAR::XML::decode($val); } push(@regs, { 'REGISTRANT_TAG' => $reg_tag{$_}, 'REGISTRANT_VAL' => $val }); } # filing values for (@{$registrant{'filing-values'}}) { my %filing = %{$_}; # filing values -- required fields @fields = ('form-type', 'act'); # filing values -- optional fields @options = ('file-number', 'film-number'); for (@options) { if ($filing{$_}) { push(@fields, $_); } } for (@fields) { push(@regs, {'REGISTRANT_TAG' => $reg_tag{$_}, 'REGISTRANT_VAL' => $filing{$_} }); } } # business address my %addr = %{$registrant{'business-address'}}; my $address = $addr{'street1'}; $address .= "
" . $addr{'street2'} if ($addr{'street2'}); $address .= "
" . $addr{'city'} if ($addr{'city'}); $address .= ", " . $addr{'state'} if ($addr{'state'}); $address .= " " . $addr{'zip'} if ($addr{'zip'}); $address .= "
" . $addr{'country'} if ($addr{'country'}); if ($address) { push(@regs, {'REGISTRANT_TAG' => $reg_tag{'business-address'}, 'REGISTRANT_VAL' => $address }); } if ($addr{'phone'}) { push(@regs, {'REGISTRANT_TAG' => $reg_tag{'phone'}, 'REGISTRANT_VAL' => $addr{'phone'} }); } # mail address %addr = %{$registrant{'mail-address'}}; $address = $addr{'street1'}; $address .= "
" . $addr{'street2'} if ($addr{'street2'}); $address .= "
" . $addr{'city'} if ($addr{'city'}); $address .= ", " . $addr{'state'} if ($addr{'state'}); $address .= " " . $addr{'zip'} if ($addr{'zip'}); $address .= "
" . $addr{'country'} if ($addr{'country'}); if ($address) { push(@regs, {'REGISTRANT_TAG' => $reg_tag{'mail-address'}, 'REGISTRANT_VAL' => $address }); } # former company data for (@{$registrant{'former-company'}}) { my %company = %{$_}; # former company -- required fields @fields = ('former-conformed-name', 'date-changed'); for (@fields) { push(@regs, {'REGISTRANT_TAG' => $reg_tag{$_}, 'REGISTRANT_VAL' => $company{$_} }); } } # spacer row push(@regs, {REGISTRANT_TAG => '', 'REGISTRANT_VAL' => ''}); } else { my($none) = "NO DATA"; my($key); foreach $key (keys %tmpl_tag) { $tmpl->param($tmpl_tag{$key} => $none); } my(@fields) = ('conformed-name', 'cik', 'irs-number', 'state-of-incorporation', 'fiscal-year-end'); my($data); my($field); foreach $field (@fields) { $data = $registrant{'company-data'}{$field}; if ($data) { $tmpl->param($tmpl_tag{$field} => $data); } } # rewrite SIC text my($val) = $registrant{'company-data'}{'assigned-sic'}; if ($val =~ /\w+/) { my($sic_html) = qq|$val"; $val = "$EDGAR::lib::sic_codes{$val} [$sic_html]"; $val = EDGAR::XML::decode($val); $tmpl->param('REG_SIC' => $val); } @fields = ('form-type', 'act', 'file-number', 'film-number'); for (@{$registrant{'filing-values'}}) { my %filing = %{$_}; foreach $field (@fields) { $data = $filing{$field}; if ($data) { $tmpl->param($tmpl_tag{$field} => $data); } } } # business address my %addr = %{$registrant{'business-address'}}; my $address = $addr{'street1'}; $address .= "
" . $addr{'street2'} if ($addr{'street2'}); $address .= "
" . $addr{'city'} if ($addr{'city'}); $address .= ", " . $addr{'state'} if ($addr{'state'}); $address .= " " . $addr{'zip'} if ($addr{'zip'}); $address .= "
" . $addr{'country'} if ($addr{'country'}); $data = $addr{'phone'}; if ($data) { $tmpl->param($tmpl_tag{'phone'} => $data); } if ($address) { $tmpl->param($tmpl_tag{'business-address'} => $address); } # mail address if (defined %{$registrant{'mail-address'}}) { %addr = %{$registrant{'mail-address'}}; $address = $addr{'street1'}; $address .= "
" . $addr{'street2'} if ($addr{'street2'}); $address .= "
" . $addr{'city'} if ($addr{'city'}); $address .= ", " . $addr{'state'} if ($addr{'state'}); $address .= " " . $addr{'zip'} if ($addr{'zip'}); $address .= "
" . $addr{'country'} if ($addr{'country'}); $tmpl->param($tmpl_tag{'mail-address'} => $address) if ($address); } @fields = ('former-conformed-name', 'date-changed'); for (@{$registrant{'former-company'}}) { my %company = %{$_}; foreach $field (@fields) { $data = $company{$field}; if ($data) { $tmpl->param($tmpl_tag{$field} => $data); } } } } } if ($version == 1) { $tmpl->param('REGISTRANTS' => \@regs); } } # # generate Documents info # sub generateDocuments { my($documents) = shift; my($parsed_docs) = shift; my($tmpl) = shift; my($tmplversion) = shift; my($parsed_tag, %ptag_hash, $doc, $doc_tag); my $debug_cnt = 0; # get parsed tables for ALL parsed documents my %parsed_tables = (); foreach $doc (@{$parsed_docs}) { for (keys %{$doc->{'parsed-tables'}}) { $doc->{'parsed-tables'}{$_} =~ /{'parsed-tables'}->{$_}; } } my @docs = (); for (@{$documents}) { my %document = %{$_}; my $text = $document{'text'}; # clean up document text a little $text = &cleanText($text); # split the text block into parsiable hunks my $textStrut = &splitText($text); # reset the text var $text = ""; my $array_ref; foreach $array_ref (@{$textStrut}) { if ($debug > 8) { $debug_cnt++; open (DEBUG, ">$array_ref->[0]-$debug_cnt.txt"); print DEBUG join("\n", @{$array_ref->[1]}); close DEBUG; } if ($array_ref->[0] eq "docTable") { ${$array_ref->[1]}[0] =~ /[0], $array_ref->[1], $array_ref->[2]); } } else { $text .= &formatText($array_ref->[0], $array_ref->[1], $array_ref->[2]); } } my $docDesc = $document{'description'}; if (!$docDesc || ($docDesc !~ /\w+/)) { $docDesc = $document{'type'}; if (!$docDesc || ($docDesc =~ /^\d+$/)) { $docDesc = "FORM " . $docDesc; } } if ($tmplversion == 1) { # _NUMBER is plus 1 due to registrant data always being first push(@docs, {'DOCUMENT_NUMBER' => $document{'sequence'} + 1, 'DOCUMENT_TITLE' => $docDesc, 'DOCUMENT_CONTENTS' => $text, 'TOC_BUG' => 'TOC' }); } else { # _NUMBER is plus 1 due to registrant data always being first push(@docs, {'DOCUMENT_NUMBER' => $document{'sequence'} + 1, 'DOCUMENT_TITLE' => $docDesc, 'DOCUMENT_CONTENTS' => $text }); } } $tmpl->param('DOCUMENTS' => \@docs); } # # generate parsed.edgar info # sub fixBrackets { my($text) = shift; # turn anchor brackets back $text =~ s#<a name="(.+)">##gm; $text =~ s#</a>##gm; # turn h4 brackets back $text =~ s#<h4>#

#gm; $text =~ s#</h4>#

#gm; $text; } # # generate parsed.edgar info # sub generateParsedDocuments { my($documents) = shift; my($tmpl) = shift; my @docs = (); for (@{$documents}) { my %document = %{$_}; # clean up document text a little my $text = $document{'parsed-form'}; return "" if (!$text); # get the form type my ($type) = ($text =~ /?/g); # " for color syntax # get the function to call for the form type to generate # the HTML my $htmlFunc = $EDGAR::Forms::htmlType{$type}; # call the subroutine, '$parseFunc' and get the parsed output. if ($htmlFunc && $text) { my $html = &$htmlFunc($text); # create PARSED_CONTENTS entry for template push(@docs, { 'PARSED_CONTENTS' => $html }); $tmpl->param('PARSED_SUBMISSION' => 1); } } $tmpl->param('PARSED_EDGAR' => \@docs); } # # generate Stamps info # sub generateStamps { my($stamps) = shift; my($tmpl) = shift; my @out_stamps = (); for (@{$stamps}) { push(@out_stamps, {'TRANSFORMER_STAMP' => $_->{'data'}}); } $tmpl->param('STAMPS' => \@out_stamps); } # # generate Table of Contents info # sub generateToC { my($edgardoc) = shift; my($tmpl) = shift; my($index, $desc, $type, $id, $anchor, $docCnt); my($tocPart, $tocItem, $tocNote, $tocTable); my($innerIndex, $tableCnt, $innerTableCnt, $partCnt, $itemCnt, $noteCnt); my %submission = %{$edgardoc}; my @docData = (); my @toc = (); my $table_toc = (); # index of security considerations and parsed submission section # (at end of documents) my $parsed_index = 2; my $security_index = 2; $docCnt = 1; $tableCnt = 1; my ($tocValue, $indexStr, @toc_table); for (@{$submission{'documents'}}) { my %document = %{$_}; my $docDesc = $document{'description'}; if (!$docDesc || ($docDesc !~ /\w+/)) { $docDesc = $document{'type'}; if (!$docDesc || ($docDesc =~ /^\d+$/)) { $docDesc = "FORM " . $docDesc; } } $docDesc = "Document " . $docCnt . ": " . $docDesc; # NUMBER is plus 1 due to registrant data always being first $index = $document{'sequence'} + 1; $anchor = "anchor" . $index; push(@toc, {'TOC_ANCHOR'=> $anchor, 'TOC_INDEX' => $index, 'TOC_TEXT' => $docDesc, 'TOC_DOCUMENT' => 1, 'TOC_PART' => 0, 'TOC_ITEM' => 0, 'TOC_NOTE' => 0, 'TOC_TABLE' => 0 }); # grab the document.item, document.part, document.note, and # document.table items (@docData) = ($document{'text'} =~ //g); $innerIndex = $innerTableCnt = $partCnt = $itemCnt = $noteCnt = 1; foreach $tocValue (@docData) { $tocPart = $tocItem = $tocNote = $tocTable = 0; # pull out the id information from the document.(item|note|part|table) # data to be used as the anchor string ($anchor) = ($tocValue =~ /.*?id=[\s|"|']+(.*?)[\s|"|']+/); # ' for color syntax ($desc) = ($tocValue =~ /.*?description=[\s|"|']+(.*)[\s|"|']+$/); # ' for color syntax ($type) = ($tocValue =~ /^(.*?)\s.*/); if ($type eq "table") { if (!$desc || ($desc !~ /\w+/)) { $desc = "Document " . $docCnt . ": Table " . $innerTableCnt; } $tocTable = 1; if ($tocTable) { $tmpl->param('HAS_TABLE' => 1); } else { $tmpl->param('HAS_TABLE' => 0); } push(@toc_table, {'TOC_ANCHOR' => $anchor, 'TOC_INDEX' => $tableCnt, 'TOC_TEXT' => $desc, 'TOC_TABLE' => $tocTable, }); $tableCnt++; $innerTableCnt++; next; } elsif ($type eq "part") { $desc = "Part " . $partCnt . ": " . $desc; $partCnt++; $tocPart = 1; } elsif ($type eq "item") { $desc = "Item " . $itemCnt . ": " . $desc; $itemCnt++; $tocItem = 1; } elsif ($type eq "note") { $desc = "Note " . $noteCnt . ": " . $desc; $noteCnt++; $tocNote = 1; } else { print STDERR "generateToC: unknown type [$type]\n" if ($debug > 1); } $indexStr = $index . "." . $innerIndex; push(@toc, {'TOC_ANCHOR' => $anchor, 'TOC_INDEX' => $indexStr, 'TOC_TEXT' => $desc, 'TOC_DOCUMENT' => 0, 'TOC_PART' => $tocPart, 'TOC_ITEM' => $tocItem, 'TOC_NOTE' => $tocNote, 'TOC_TABLE' => $tocTable }); $innerIndex++; } $security_index++; $parsed_index++; $docCnt++; } $tmpl->param('TOC' => \@toc); $tmpl->param('TOC_TABLE' => \@toc_table); # if there's a parsed submission, the number associated with the # security item in the list needs to bump up 1 my $parsedSub = $tmpl->param('PARSED_SUBMISSION'); if ($parsedSub) { $security_index++; } # security index is last -- for now $tmpl->param('SECURITY_INDEX' => $security_index); $tmpl->param('PARSED_INDEX' => $parsed_index); } sub extractSection { my($data) = shift; my($start_text) = shift; my($end_text) = shift; # extracted section data my($sect) = ""; $$data =~ /(${start_text}.*?${end_text})/gs && ($sect = $1); if ($sect) { # remove extracted section from data $$data =~ s/\Q$sect\E\n?//gs; # remove start/end tags from result $sect =~ s/${start_text}|$end_text//gs; # eat leading/trailing blank lines $sect =~ s/^(\s*\n)+|(\s*\n)+$//gs; } # return extracted section text $sect; } sub getNumberOfCols { my $text = shift; my($num_of_cols, $cols); my $done = 0; while (!$done) { $text =~ s@\s+(.+?)@@s; $cols = $1; next if ($cols =~ /colspan/); $num_of_cols = $cols =~ tr/\n/\n/; $done = 1; } return $num_of_cols } # # generate HTML version of parsed edgar table # sub parsedTable2html { my($xml) = shift; my $html = ''; # save table description, if available $xml =~ s@@@; # " for color syntax my $id = $1; $id = "\n"; # strip table element but save table description, if available $xml =~ s@@@gs; # strip table close element $xml =~ s@@@gs; # extract table parts my $caption = &extractSection(\$xml, "", ""); my $header = &extractSection(\$xml, "", ""); $header = &EDGAR::XML::encode($header); my $footer = &extractSection(\$xml, "", ""); $footer = &EDGAR::XML::encode($footer); # everything else is body data my $body = $xml; # strip leading/trailing blank lines $body =~ s@^(\s*\n)+@@s; $body =~ s@(\s*\n)+$@@s; # remove the tbody tag $body =~ s@@@gs; # rows $body =~ s@<(/?)trow>@<$1TR>@gs; # columns $body =~ s@ ?<(/?)tcol[^>]*>@<$1TD>@gs; # open the HTML table $html = ""; # table header my $num_of_cols; if ($header) { $num_of_cols = &getNumberOfCols($xml); $html .= "\n"; } # caption? if ($caption) { $caption = &parsedTableCaption2html($caption); $html .= $caption; } # table body $html .= $body . "\n"; # table footer if ($footer) { $num_of_cols = &getNumberOfCols($xml) if (!$num_of_cols); $footer =~ s/---+|___+|===+//g; $html .= ""; } # close the HTML table $html .= "
$header
$footer
" . "\n"; $html = $id . $html; } sub parsedTableCaption2html { my $caption = shift; # strip leading/trailing blank lines $caption =~ s@^(\s*\n)+@@s; $caption =~ s@(\s*\n)+$@@s; # rows $caption =~ s@<(/?)trow>@<$1TR>@gs; # columns $caption =~ s@ ?<(/?)tcol[^>]*>@<$1TH>@gs; if ($caption =~ /colspan/) { # deal with colspan # make into array my(@array) = split(/\n/, $caption); $caption = ""; my($i, $colspan, $data); $colspan = 0; for $i (0 .. $#array) { if ($colspan) { $colspan--; next; } if ($array[$i] =~ m@colspan=("\d+")[^>]*>([^<]*)<@) { $colspan = $1; $data = $2; $caption .= " "; $caption .= &EDGAR::XML::encode($data) . "\n"; $colspan--; } else { $caption .= $array[$i] . "\n"; } } $caption .= " \n"; } else { $caption =~ s@<(/?)tcol.*?>@<$1TH>@gs; } return $caption; } # # get an element array from an XML tag # sub getElementArr { my($elementName) = shift; my($text) = shift; my(@elementArr) = ($text =~ /(<$elementName>.*?<\/$elementName>)/gs); my $element; if ($debug > 1) { foreach $element (@elementArr) { print STDERR "$elementName: $element\n"; } } return(@elementArr); } # # get an element from an XML tag # sub getElement { my($elementName) = shift; my($text) = shift; my($element) = ($text =~ /<$elementName.*?>(.*?)<\/$elementName>/s); if ($debug > 1) { print STDERR "$elementName: $element\n"; } $element; } # # get an element from an XML tag # sub getElementAll { my($elementName) = shift; my($text) = shift; my($element) = ($text =~ /(<$elementName.*?>.*?<\/$elementName>)/s); if ($debug > 1) { print STDERR "$elementName: $element\n"; } $element; } # # get an attribute from an item # sub getAttribute { my($element) = shift; my($attributeName) = shift; my($text) = shift; my($attribute) = ($text =~ /<$element.*?$attributeName\s*=['|"](.*?)['|"].*>/); # " for color syntax only if ($debug > 1) { print STDERR "$element ($attributeName): $attribute\n"; } $attribute; } # # get an attribute array from an item # sub getAttributeArr { my($element) = shift; my($attributeName) = shift; my($text) = shift; my(@attributeArr) = ($text =~ /<$element.*?$attributeName\s*=['|"](.*?)['|"].*?>/gs); # " for color syntax only my $attribute; if ($debug > 1) { foreach $attribute (@attributeArr) { print STDERR "$element ($attributeName): $attribute\n"; } } return(@attributeArr); } ####################################################### ### paul miller pmiller new subs here ####################################################### # # do some minor clean up for all the text in a document # sub cleanText { my($text) = shift; $text =~ s@@@gs; # get rid of large sections of blanks lines, messes up FromText $text =~ s/\n{5,}\n/\n\n/g; # remove PAGE tags and page numbers $text =~ s@^\s*\s*\n@\n\n@gm; $text =~ s@^\s*\s+PAGE\s+\d+\s*\n@\n\n@gm; $text =~ s@^\s*SCREEN NUMBER:\s+\d+\s+PAGE NUMBER:\s+\d+@\n\n@gm; # remove tags $text =~ s@@@gs; # remove numbers that are by themselves $text =~ s/^\s*\d+\s*$//gm; # XML entity clean up -- text2html encodes & -> & $text = EDGAR::XML::decode($text); # clean up HTML/PDF document links $text =~ s@<(html|img|pdf)\s+src="([^"]+?)"\s*/>@$2@gs; # " for color syntax $text; } # # split text in to parsable hunks # sub splitText { my($text) = shift; my(@textStruct, $type, $data_ref, $hints); my @textList = split(/\n/, $text); my $textList_aref = \@textList; my @array; # title text if exists is always first &gatherDebuggingInfo_start("title_split"); $data_ref = &splitTitleText($textList_aref); &gatherDebuggingInfo_end("title_split", $data_ref, "title_split"); $array[0] = "title"; $array[1] = $data_ref; $array[2] = ""; push(@textStruct, \@array); &gatherDebuggingInfo_start("unknown"); ($data_ref, $type, $hints) = &splitUnknownTypeText($textList_aref); &gatherDebuggingInfo_end($type . "_split", $data_ref, "unknown"); my $cnt; while ($type ne "done") { my(@array); $array[0] = $type; $array[1] = $data_ref; $array[2] = $hints; push(@textStruct, \@array); &gatherDebuggingInfo_start("unknown"); ($data_ref, $type, $hints) = &splitUnknownTypeText($textList_aref); &gatherDebuggingInfo_end($type . "_split", $data_ref, "unknown"); } return (\@textStruct); } # # returns 1 if the text is centered # sub centeredText { my ($line) = shift; my ($lineLength) = 80; my ($error_padding) = 15; # number of char away from center and # still called centered text my ($frontPad, $sentenceLength, $ratio); $line =~ /^(\s*)(\S.+)/; $frontPad = length($1); $sentenceLength = length($2); # if line starts with 11 spaces or less spaces not centered return 0 if ($frontPad < 12); $ratio = ($frontPad*2 + $sentenceLength) - ($lineLength); # should be zero if ( abs($ratio) > $error_padding ) { return 0; # not centered } else { return 1; # centered } } # # this is a known type of text, must come first. # Does a minimum processing on the text, and splits it from the rest of # the text. # sub splitTitleText { my($text_aref) = shift; my($newText, $line, $realTitleoff, $endHeader); my ($addedTitleInfo) = 0; my ($headerCnt) = 0; if ($#{$text_aref} < 6) { # no title with this few of lines $logger::DEBUG->saveErrorsCurrent('-error' => "small doc length [$#{$text_aref}] no title"); return []; } my $index = -1; while (++$index < $#{$text_aref}) { # some documents have info before the title # skip this "extra" info $line = $text_aref->[$index]; next if (!$line || ($line =~ /^\s+$/) || ($line =~ /^[-_= ]+---|___|===[-_= ]+$/)); last if (($line =~ /^\s/) || ($line =~ /\ 10) { # can't find the real title, skip it $index = 0; last; } } $text_aref->[$index] = "~~~TITLE-START~~~" . $text_aref->[$index]; while (++$index < $#{$text_aref}) { $line = $text_aref->[$index]; next if (!$line || ($line =~ /^\s+$/) || ($line =~ /^[-_= ]+---|___|===[-_= ]+$/)); # end title on any document tags last if ($line =~ /\[$index] =~ /^\s*$/) { last if ($index > $#{$text_aref}); $index++; # find non-empty line } # two non-centered lines in a row, end of title last if ( !¢eredText($text_aref->[$index]) ); } } my @array = splice(@{$text_aref}, 0, $index-1); return \@array; } # # the document table type of text. ..
# note these should also be in parsed.table # sub splitDocumentTable { my $text_aref = shift; my $index = -1; while (++$index < $#{$text_aref}) { last if ($text_aref->[$index] =~ m@[0] =~ s/~~~TABLE-OF-CONTENTS~~~//; my $index = -1; # move down until out of Table of Contents while (++$index <= $#{$text_aref}) { last if ($text_aref->[$index] =~ /<\/?document[\.-]/); next if ($text_aref->[$index] =~ /^\s+$/); next if ($text_aref->[$index] =~ /\w\s*\.{5,}\s*\w/); # test next line next if ($text_aref->[$index+1] =~ /\w\s*\.{5,}\s*\w/); # test next line next if ($text_aref->[$index+2] =~ /\w\s*\.{5,}\s*\w/); # nope, get out last; } my @array = splice(@{$text_aref}, 0, $index); return (\@array); } #################################### # name : splitTextTable # input : an array ref # output: list 1 - string : table text # 2 - array ref : the standard columns for the table # side effects : the input ref gets changed # # describtion: # splits out the text table type of text for the rest of the text # sub splitTextTable { my($text_aref) = shift; my($table_row, @this_lines_cols); # get rid of my Table Tag and keep the std_cols $text_aref->[0] =~ s/~~~TEXT-TABLE~~~\[([^]]+)\]//; my @std_cols = split(/\s/, $1); # find the end of the table my $index = 0; # get the first one for free while (++$index <= $#{$text_aref}) { last if (!$text_aref->[$index] || ($text_aref->[$index] =~ /^\s+$/)); next if ($text_aref->[$index] =~ /^[-|_|= ]+---|___|===[-|_|= ]+$/); # test to see if the columns all line up # stay in table if "close" to being okay @this_lines_cols = (); push @this_lines_cols, 0 if ($text_aref->[$index] !~ /^\s\s/); while ($text_aref->[$index] =~ /\s( +)(?=[^ ])/g) { push @this_lines_cols, pos($text_aref->[$index]); } $table_row = &EDGAR::Table::inTableRow(\@std_cols, \@this_lines_cols); if (!$table_row) { # this row is not in the table, test next row last if (!$text_aref->[$index+1] || ($text_aref->[$index+1] =~ /^\s+$/)); @this_lines_cols = (); push @this_lines_cols, 0 if ($text_aref->[$index+1] !~ /^\s\s/); while ($text_aref->[$index+1] =~ /\s( +)(?=[^ ])/g) { push @this_lines_cols, pos($text_aref->[$index+1]); } $table_row = &EDGAR::Table::inTableRow(\@std_cols, \@this_lines_cols); last if (!$table_row); } } my @new_text = splice(@{$text_aref}, 0, $index); return (\@new_text, \@std_cols); } #################################### # name : splitUnknownTypeText # input : an array ref # output: list 1 - string : text # 2 - string : the type of text # 3 - array ref : (currently only for tables), # the standard column positions # side effects : the input ref gets changed # # describtion: # takes an unknown type of text, figure out what type of text it is, # and split it from the rest of the text. # sub splitUnknownTypeText { my($text_aref) = shift; my($array_ref, $line, $hints); my($line_ref, $new_line_ptr); my $centered = 0; my $prev_line = ""; my $type = "general"; # the default type return (undef, "done", "") if ($#{$text_aref} < 0); # look at the first line of this text section $line = $text_aref->[0]; if ($line =~ /[$line_ptr]; # we are now in the "general" text type last if ($line =~ /\[0] .= "~~~TEXT-TABLE~~~[@std_columns]"; return (\@array, $type, ""); } # check to see if we are in the Table Of Content $new_line_ptr = &ifTableOfContent($line_ptr, $text_aref); if ($new_line_ptr) { my @array = splice(@{$text_aref}, 0, $new_line_ptr); $text_aref->[0] .= "~~~TABLE-OF-CONTENTS~~~"; return (\@array, $type, ""); } $prev_line = $line; } my @array = splice(@{$text_aref}, 0, $line_ptr); return (\@array, $type, ""); } sub ifTableOfContent { my($line_ptr) = shift; my($text_aref) = shift; my($inToC); my $i = $line_ptr; if ($text_aref->[$line_ptr] =~ /^\s*TABLE OF CONTENTS?\s*$/i) { # looking for "TABLE OF CONTENTS" then following lines of # WORDS..........WORDS while (++$i < $line_ptr+10) { # not in a ToC return 0 if ($text_aref->[$i] =~ /<\/?document[\.-]/); # return the first line of the ToC return $i if ($text_aref->[$i] =~ /\w\s*\.{5,}\s*\w/); } # did not find the first line of ToC which in 10, give up return 0; } elsif ($text_aref->[$line_ptr] =~ /\w\s*\.{5,}\s*\w/) { return 0 if ($text_aref->[$line_ptr] =~ /<\/?document[\.-]/); # check lines below, need three line for ToC $inToC = 0; while (++$i < $line_ptr+6) { return 0 if ($text_aref->[$i] =~ /<\/?document[\.-]/); if ($text_aref->[$i] =~ /\w\s*\.{5,}\s*\w/) { $inToC++; } } return 0 if ($inToC < 2); $i = $line_ptr; # check lines above, stop on an empty line, or a tag while (--$i > 0) { if (!$text_aref->[$i] || ($text_aref->[$i] =~ /^\s+$/) || ($text_aref->[$i] =~ /<\/?document[\.-]/)) { return $i ? $i : 1; } } } return 0; } sub fixTableOfContents { my($text) = shift; my(%toc_hash, $new_text, $row_aref, $length, $spaces); %toc_hash = &parseTableOfContents($text); foreach $row_aref (@{$toc_hash{'body'}}) { $length = $toc_hash{'max_article'}; $spaces = $length - length($row_aref->[0]); $row_aref->[0] .= sprintf(" ") x $spaces; $length = $toc_hash{'max_section'}; $spaces = $length - length($row_aref->[1]); $row_aref->[1] .= sprintf(" ") x $spaces; $length = $toc_hash{'max_description'}; $spaces = $length - length($row_aref->[2]); $row_aref->[2] .= sprintf(" ") x $spaces; $new_text .= $row_aref->[0] ." ". $row_aref->[1] ." ". $row_aref->[2] ." ". $row_aref->[3] . "\n"; } return $new_text; } # # toc_hash is # page -> if exists "PAGE" header # toc -> if exists "TABLE OF CONTENTS" header # header -> if exists any other header stuff # body -> \@@toc_list # max_article -> max length of the article part # max_section -> max length of the section part # max_description -> max length of the description part # # \@toc_list is # 0 -> article # 1 -> section # 2 -> description # 3 -> page number # sub parseTableOfContents { my($text) = shift; my(%toc_hash); if (($text =~ /ARTICLE/) && ($text =~ /SECTION/)) { %toc_hash = &parseTableOfContentsARTICLE($text); return %toc_hash; } return (); } sub parseTableOfContentsARTICLE { my($text) = shift; my(@toc_list, %toc_hash, $i, $cnt); my(@textArray) = split(/\n/, $text); $i = 0; # get header while ($textArray[$i] !~ /\w\.\.\.+\w/) { last if ($i > $#textArray); if ($textArray[$i] =~ /^\s+Page\s*$/i) { $toc_hash{'page'} = "Page"; } elsif ($textArray[$i] =~ /TABLE OF CONTENTS/i) { $toc_hash{'toc'} = "TABLE OF CONTENTS"; } elsif ($textArray[$i] =~ /\S/) { $toc_hash{'header'} .= $textArray[$i]; } $i++; } my($article, $section, $description, $pageNum); my($max_article, $max_section, $max_description, $length); for ($cnt=$i; $cnt<=$#textArray; $cnt++) { next if ($textArray[$cnt] =~ /^\s+$/); $article = " "; $section = " "; $description = " "; $pageNum = " "; if ($textArray[$cnt] =~ s/^\s*(ARTICLE[^\.]+)\.+//) { $article = $1; $length = length($article); $max_article = $length if ($length > $max_article); ($description) = $textArray[$cnt] =~ /(.+?)\s+\d+$/; $length = length($description); $max_description = $length if ($length > $max_description); ($pageNum) = $textArray[$cnt] =~ /(\d+)\s*$/; $pageNum = " " if (!$pageNum); my(@tmp_array); # keep ref push(@tmp_array, ($article, $section, $description, $pageNum)); $toc_list[$i] = \@tmp_array; $i++; } elsif ($textArray[$cnt] =~ s/^\s*(SECTION\s+[\d\.]+)//) { $section = $1; $length = length($section); $max_section = $length if ($length > $max_section); ($description) = $textArray[$cnt] =~ /^\s*([^\.]+)/; $length = length($description); $max_description = $length if ($length > $max_description); ($pageNum) = $textArray[$cnt] =~ /(\d+)\s*$/; $pageNum = " " if (!$pageNum); my(@tmp_array); # keep ref push(@tmp_array, ($article, $section, $description, $pageNum)); $toc_list[$i] = \@tmp_array; $i++; } else { ($description) = $textArray[$cnt] =~ /^\s*([^\.]+)/; ($pageNum) = $textArray[$cnt] =~ /(\d+)\s*$/; $toc_list[$i-1][2] =~ s/\s*$/ /; $toc_list[$i-1][2] .= $description; $pageNum = " " if (!$pageNum); $toc_list[$i-1][3] = $pageNum; $length = length($toc_list[$i-1][2]); $max_description = $length if ($length > $max_description); } } $toc_hash{'max_article'} = $max_article; $toc_hash{'max_section'} = $max_section; $toc_hash{'max_description'} = $max_description; $toc_hash{'body'} = \@toc_list; return %toc_hash; } # # formate the text into HTML # sub formatText { my($type) = shift; my($text_ref) = shift; my($hints) = shift; my $text; &gatherDebuggingInfo_start("known"); # yes I know the type if ($type eq "title") { $text = &formatTitleText($text_ref); } elsif ($type eq "general") { $text = &formatGeneralText($text_ref); } elsif ($type eq "docTable") { $text = &formatDocumentTable($text_ref); } elsif ($type eq "textTable") { $text = &formatTextTable($text_ref, $hints); } elsif ($type eq "tableOfContents") { $text = &formatTableOfContents($text_ref); } else { # if here, a major problem! print STDERR "edgar-html.pl: formatText Error unknown type [$type]\n" if ($debug > 1); $logger::DEBUG->saveErrorsCurrent('-error' => "unknown type [$type]"); } &gatherDebuggingInfo_end_text($type . "_format", $text, "known"); $text; } # # formate this type text (title text) into HTML # sub formatTitleText { my($text_ref) = shift; my $text = join("\n", @{$text_ref}); return "" if (!$text || ($text =~ /^\s+$/)); # get rid of long dashed lines $text =~ s/^[-|_|= ]+---|___|===[-|_|= ]+$//gm; $text =~ s/\n/
\n/g; $text =~ s/~~~TITLE-START~~~/

\n/; $text .= "

\n"; } # # formate this type text (general text) into HTML # sub formatGeneralText { my $text_ref = shift; my $text = join("\n", @{$text_ref}); return "" if (!$text || ($text =~ /^\s+$/s)); # get rid of long dashed lines $text =~ s/^[-|_|= ]+---|___|===[-|_|= ]+$//gm; # change [o . -] to * for bullets in unordered lists $text =~ s/^\s+[o\.-]\s+/ * /gm; # get rid of large blocks of empty text $text =~ s/\n[ \n]+\n/\n\n/g; $text =~ s/(\[.?.?\].*$)/$&~~~BR~~~/gm; # add Line Breaks after lines with dots (.....) $text =~ s/^([^\.]+\.{5,}.+)$/$1~~~BR~~~/gm; # keep the footnotes, put them on a seperate line $text =~ s@<(/?F[^>]+)>@\n\n~~~FOOTNOTE~~~$1~~~ETONTOOF~~~\n\n@gs; $text = text2html($text, paras => 1, bullets => 1, urls => 1, email => 1); $text = &makeDocTags($text); # change footnotes back $text =~ s/~~~FOOTNOTE~~~([^~]+)~~~ETONTOOF~~~/<$1>/gs; # change BR tags $text =~ s/~~~BR~~~/
/g; $text; } # # formate Document taged tables into HTML # sub formatDocumentTable { my $text_ref = shift; my $text = join("\n", @{$text_ref}); return "" if (!$text || ($text =~ /^\s+$/)); $logger::DEBUG->saveErrorsCurrent('-error' => "failing to a pre"); # remove any custom tags $text =~ s/~~~[^~]+~~~//g; $text =~ s@@@g; $text =~ s@@@g; $text =~ s@@@g; $text =~ s@@@g; $text = text2html($text, urls => 1, email => 1, pre => 1); $text = &makeDocTags($text); $text; } # # formate text tables into HTML # sub formatTextTable { my $text_ref = shift; my $std_col_aref = shift; my $html = "
\n"; $html .= &EDGAR::Table::textTable2HTML($text_ref, $std_col_aref); $html .= "
\n"; # remove any other custom tags $html =~ s/~~~[^~]+~~~//g; $html; } sub formatTableOfContents { my $text_ref = shift; my $text = join("\n", @{$text_ref}); my $untouched = $text; # keep the footnotes, put them on a seperate line $text =~ s@<(/?F[^>]+)>@\n\n~~~FOOTNOTE~~~$1~~~ETONTOOF~~~\n\n@gs; # try and parse the ToC $text = &fixTableOfContents($text); if ($text) { $text = &text2html($text, paras => 1, urls => 1, email => 1, tables => 1); } else { $text = "could not fix the table of contents, use untouched"; } if ($text !~ //) { # the text2html could not make it a table, fail to a pre $text = text2html($untouched, urls => 1, email => 1, pre => 1); $logger::DEBUG->saveErrorsCurrent('-error' => "failing to a pre"); } $text = &makeDocTags($text); # change footnotes back $text =~ s@\n~~~FOOTNOTE~~~([^~]+)~~~ETONTOOF~~~\n@<$1>@g; # remove the problem tag if there $text =~ s/~~~TABLE-PROBLEM~~~//; $text; } sub addTableStyleSheet { my($text) = shift; # center it $text = "
\n" . $text . "\n
"; $text =~ s@@@gm; $text =~ s@@@gm; $text; } # # The text2html changed the document.table tags, change them back here # sub makeDocTags { my($doc) = shift; my($docWithTags,$line); foreach $line (split(/\n/, $doc)) { if ($line =~ /^([^\&]*)\<document[\.-]\S+ id=\"([^\&]+)/) { $line = "

$1\n\n"; } $line =~ s@</document[\.-]\S+>@
@; $docWithTags .= $line."\n"; } $docWithTags; } sub gatherDebuggingInfo_start { my $name = shift; $logger::DEBUG->current('-name' => $name); $logger::DEBUG->timerOnCurrent(); } sub gatherDebuggingInfo_end { my $name = shift; my $amount_ref = shift; my $del_name = shift; $logger::DEBUG->increment('-name' => $name); # increament the group $logger::DEBUG->changeCurrent('-name' => $name, '-del-name' => $del_name); $logger::DEBUG->timerOffCurrent(); $logger::DEBUG->currentLines('-value' => $#{$amount_ref}); } sub gatherDebuggingInfo_end_text { my $name = shift; my $text = shift; my $del_name = shift; $logger::DEBUG->increment('-name' => $name); # increament the group $logger::DEBUG->changeCurrent('-name' => $name, '-del-name' => $del_name); $logger::DEBUG->timerOffCurrent(); $logger::DEBUG->currentLines('-value' => $text); } ####################################################### ## paul miller pmiller end of new subs ####################################################### # # generate HTML from parsed edgar for beneficial 1 data # sub edgarBeneficial1 { my($text) = shift; my($html) = ""; if ($debug > 1) { print STDERR "TEXT IN:\n$text\n\n"; } # # HEADER # my($class) = getAttribute("parsed.form", "class", $text); my($sequence) = getAttribute("parsed.form", "sequence", $text); my($type) = getAttribute("parsed.form", "type", $text); # my ($header) = getElement("header.b1", $text); # # my ($issuer) = getElementAll("issuer.b1", $header); my($issuerName) = getAttribute("issuer.b1", "name", $issuer); my($issuerSymbol) = getAttribute("issuer.b1", "symbol", $issuer); my($issuerIrsId) = getElement("irs-id", $issuer); my($filedBy) = getAttribute("filedBy", "type", $issuer); my($fileNumber) = getElement("fileNumber", $issuer); my($issuerStreet) = getElement("street", $issuer); my($issuerCity) = getElement("city", $issuer); my($issuerState) = getElement("region", $issuer); my($issuerZip) = getElement("code", $issuer); my($issuerCountry) = getElement("country", $issuer); # # my($filer) = getElementAll("filer", $header); my($filerName) = getAttribute("filer", "fullName", $filer); my($filerIrsId) = getElement("irs-id", $filer); my($addendum) = getAttribute("relationshipToIssuer", "addendum", $filer); my($director) = getAttribute("relationshipToIssuer", "director", $filer); my($officer) = getAttribute("relationshipToIssuer", "officer", $filer); my($owner) = getAttribute("relationshipToIssuer", "owner", $filer); my($other) = getAttribute("relationshipToIssuer", "other", $filer); my($filerStreet) = getElement("street", $filer); my($filerCity) = getElement("city", $filer); my($filerState) = getElement("region", $filer); my($filerZip) = getElement("code", $filer); my($filerCountry) = getElement("country", $filer); # # my($eventDay) = getAttribute("eventDate", "day", $header); my($eventMonth) = getAttribute("eventDate", "month", $header); my($eventYear) = getAttribute("eventDate", "year", $header); # # my($originalDay) = getAttribute("originalDate", "day", $header); my($originalMonth) = getAttribute("originalDate", "month", $header); my($originalYear) = getAttribute("originalDate", "year", $header); # # my($securityTitle) = getElement("securityTitle", $header); # # my($broker) = getElementAll("broker", $header); my($brokerName) = getAttribute("fullName", "broker", $broker); my($brokerNumber) = getElement("brokerNumber", $broker); my($brokerStreet) = getElement("street", $broker); my($brokerCity) = getElement("city", $broker); my($brokerState) = getElement("region", $broker); my($brokerZip) = getElement("code", $broker); my($brokerCountry) = getElement("country", $broker); # my($numberShares) = getElement("numberShares", $header); # # my($marketValue) = getElementAll("marketValue", $header); my($marketValueCurrency) = getAttribute("marketValue", "currency", $marketValue); my($marketValueValue) = getAttribute("marketValue", "value", $marketValue); # # my($marketDay) = getAttribute("marketDate", "day", $marketValue); my($marketMonth) = getAttribute("marketDate", "month", $marketValue); my($marketYear) = getAttribute("marketDate", "year", $marketValue); # my($numberOutstanding) = getElement("numberOutstanding", $header); # # my($saleDay) = getAttribute("saleDate", "day", $header); my($saleMonth) = getAttribute("saleDate", "month", $header); my($saleYear) = getAttribute("saleDate", "year", $header); # # my($securitiesExchange) = getElement("securitiesExchange", $header); # HTMLize HEADER data $html .= "

$class

\n"; $html .= "
([\%\$\d,\.\(\) ]+)$1(.+?)$1
\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Type:$type
Sequence:$sequence
\n"; $html .= "

\n"; $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Issuer Name:$issuerName
Issuer Symbol:$issuerSymbol
Issuer IRS Id:$issuerIrsId
Filed By:$filedBy
File Number:$fileNumber
Issuer Address:$issuerStreet
\n"; $html .= " $issuerCity, $issuerState $issuerZip
\n"; $html .= " $issuerCountry
Filer Name:$filerName
Filer IRS Id:$filerIrsId
Filer Relationship to Issuer:director = $director
\n"; $html .= " officer = $officer
\n"; $html .= " owner = $owner
\n"; $html .= " other = $other
\n"; $html .= " addendum = $addendum
Filer Address:$filerStreet
\n"; $html .= " $filerCity, $filerState $filerZip
\n"; $html .= " $filerCountry
Event Date:$eventMonth $eventDay, $eventYear
Original Date:$originalMonth $originalDay, $originalYear
Security Title:$securityTitle
Broker Name:$brokerName
Broker Number:$brokerNumber
Broker Address:$brokerStreet
\n"; $html .= " $brokerCity, $brokerState $brokerZip
\n"; $html .= " $brokerCountry
Number of Shares:$numberShares
Market Value:$marketValueValue $marketValueCurrency
Market Date:$marketMonth $marketDay, $marketYear
Number Outstanding:$numberOutstanding
Sale Date:$saleMonth $saleDay, $saleYear
Securities Exchange:$securitiesExchange
\n"; $html .= "

\n"; # # NON-DERIVATIVE # if ($type eq "144") { $html .= "

Securities to be Sold

\n"; } else { $html .= "

Non-Derivative Securities Beneficially Owned

\n"; } # my (@nonDerivative) = getElementArr("nonDerivative", $text); my $nonDeriv; foreach $nonDeriv (@nonDerivative) { my($securityTitle) = getElement("securityTitle", $nonDeriv); # # my($ownership) = getAttribute("ownership", "form", $nonDeriv); if ($ownership eq "D") { $ownership = "direct"; } elsif ($ownership eq "I") { $ownership = "indirect"; } # my($natureOfOwnership) = getElement("natureOfOwnership", $nonDeriv); # my($amountOwned) = getElement("amountOwned", $nonDeriv); # # my($transactionDay) = getAttribute("transactionDate", "day", $nonDeriv); my($transactionMonth) = getAttribute("transactionDate", "month", $nonDeriv); my($transactionYear) = getAttribute("transactionDate", "year", $nonDeriv); # # my($transactionCode) = getAttribute("transactionCode", "code", $nonDeriv); my($transactionVCode) = getAttribute("transactionCode", "v.code", $nonDeriv); # # my($acqDisAmount) = getAttribute("acquireDispose", "amount", $nonDeriv); my($acqDisPrice) = getAttribute("acquireDispose", "price", $nonDeriv); my($acqDis) = getAttribute("acquireDispose", "acquiredOrDisposed", $nonDeriv); if ($acqDis eq "A") { $acqDis = "acquired"; } elsif ($acqDis eq "D") { $acqDis = "disposed"; } my($securitiesAcq) = getAttribute("acquireDispose", "securitiesAcquired", $nonDeriv); my($securitiesDis) = getAttribute("acquireDispose", "securitiesDisposed", $nonDeriv); my($footnote) = getAttribute("acquireDispose", "footnote", $nonDeriv); # my($amountOwnedEOY) = getElement("amountOwnedEOY", $nonDeriv); # my($amountOwnedEOM) = getElement("amountOwnedEOM", $nonDeriv); # HTMLize NON-DERIVATIVE data $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Security Title:$securityTitle
Ownership:$ownership
Nature of Ownership:$natureOfOwnership
Amount Owned:$amountOwned
Transaction Date:$transactionMonth $transactionDay, $transactionYear
Transaction Code:$transactionCode
Amount Acquired or Disposed:$acqDisAmount
Price:$acqDisPrice
Acquired or Disposed:$acqDis
Securities Acquired:$securitiesAcq
Securities Disposed:$securitiesDis
Amount Owned at End of Year:$amountOwnedEOY
Amount Owned at End of Month:$amountOwnedEOM
\n"; $html .= "

\n"; } # # DERIVATIVE # if ($type eq "144") { $html .= "

Securities Sold During the Past Three Months

\n"; } else { $html .= "

Derivative Securities Beneficially Owned

\n"; } # my (@derivative) = getElementArr("derivative", $text); my $deriv; foreach $deriv (@derivative) { my($securityTitle) = getElement("securityTitle", $deriv); # # my($exercisableDay) = getAttribute("exercisableDate", "day", $deriv); my($exercisableMonth) = getAttribute("exercisableDate", "month", $deriv); my($exercisableYear) = getAttribute("exercisableDate", "year", $deriv); # # my($expirationDay) = getAttribute("expirationDate", "day", $deriv); my($expirationMonth) = getAttribute("expirationDate", "month", $deriv); my($expirationYear) = getAttribute("expirationDate", "year", $deriv); # # my($underlyingSecurity) = getElementAll("underlyingSecurity", $deriv); my($underlyingSecurityTitle) = getAttribute("underlyingSecurity", "securityTitle", $underlyingSecurity); # # my($price) = getAttribute("price", "dollarValue", $deriv); # # my($ownership) = getAttribute("ownership", "form", $deriv); if ($ownership eq "D") { $ownership = "direct"; } elsif ($ownership eq "I") { $ownership = "indirect"; } # my($natureOfOwnership) = getElement("natureOfOwnership", $deriv); # my($amountOwnedEOY) = getElement("amountOwnedEOY", $deriv); # my($amountOwnedEOM) = getElement("amountOwnedEOM", $deriv); # # my($transactionDay) = getAttribute("transactionDate", "day", $deriv); my($transactionMonth) = getAttribute("transactionDate", "month", $deriv); my($transactionYear) = getAttribute("transactionDate", "year", $deriv); # # my($transactionCode) = getAttribute("transactionCode", "code", $deriv); my($transactionVCode) = getAttribute("transactionCode", "v.code", $deriv); # # my($acqDisAmount) = getAttribute("acquireDispose", "amount", $deriv); my($acqDisPrice) = getAttribute("acquireDispose", "price", $deriv); my($acqDis) = getAttribute("acquireDispose", "acquiredOrDisposed", $deriv); if ($acqDis eq "A") { $acqDis = "acquired"; } elsif ($acqDis eq "D") { $acqDis = "disposed"; } my($securitiesAcq) = getAttribute("acquireDispose", "securitiesAcquired", $deriv); my($securitiesDis) = getAttribute("acquireDispose", "securitiesDisposed", $deriv); my($footnote) = getAttribute("acquireDispose", "footnote", $deriv); # HTMLize DERIVATIVE data $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Security Title:$securityTitle
Exercisable Date:$exercisableMonth $exercisableDay, $exercisableYear
Expiration Date:$expirationMonth $expirationDay, $expirationYear
Underlying Security Title:$underlyingSecurityTitle
Price:$price
Ownership:$ownership
Nature of Ownership:$natureOfOwnership
Amount Owned at End of Year:$amountOwnedEOY
Amount Owned at End of Month:$amountOwnedEOM
Transaction Date:$transactionMonth $transactionDay, $transactionYear
Transaction Code:$transactionCode
Amount Acquired or Disposed:$acqDisAmount
Price:$acqDisPrice
Acquired or Disposed:$acqDis
Securities Acquired:$securitiesAcq
Securities Disposed:$securitiesDis
\n"; $html .= "

\n"; } # # FOOTER # # my($footer) = getElement("footer", $text); my(@signature) = getElementArr("signature", $footer); my($signatureDay) = getAttribute("signatureDate", "day", $footer); my($signatureMonth) = getAttribute("signatureDate", "month", $footer); my($signatureYear) = getAttribute("signatureDate", "year", $footer); # HTMLize FOOTER data $html .= "\n"; my $sig; foreach $sig (@signature) { $html .= " \n"; $html .= " \n"; $html .= " \n"; } $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Signature:$sig
Signature Date:$signatureMonth $signatureDay, $signatureYear
\n"; if ($debug > 1) { print STDERR "\n\n\n************* HTML **********\n\n$html\n\n"; } $html; } # # generate HTML from parsed edgar for beneficial 2 data # sub edgarBeneficial2 { my($text) = shift; my($html) = ""; if ($debug > 1) { print STDERR "TEXT IN:\n$text\n\n"; } # # HEADER # my($class) = getAttribute("parsed.form", "class", $text); my($sequence) = getAttribute("parsed.form", "sequence", $text); my($type) = getAttribute("parsed.form", "type", $text); # my ($header) = getElement("header.b2", $text); # my ($amendmentNum) = getElement("amendmentNumber", $header); # # my($issuer) = getElementAll("issuer.b2", $header); my($issuerName) = getAttribute("issuer.b2", "name", $header); my($issuerSymbol) = getAttribute("issuer.b2", "symbol", $header); my($issuerStreet) = getElement("street", $issuer); my($issuerCity) = getElement("city", $issuer); my($issuerState) = getElement("region", $issuer); my($issuerZip) = getElement("code", $issuer); my($issuerCountry) = getElement("country", $issuer); # # my($securityTitle) = getElement("securityTitle", $header); # my($cusip) = getElement("cusip", $header); # # my($eventDay) = getAttribute("eventDate", "day", $header); my($eventMonth) = getAttribute("eventDate", "month", $header); my($eventYear) = getAttribute("eventDate", "year", $header); # # my($contact) = getElementAll("contact", $header); my($contactName) = getAttribute("fullName", "contact", $contact); my($contactStreet) = getElement("street", $contact); my($contactCity) = getElement("city", $contact); my($contactState) = getElement("region", $contact); my($contactZip) = getElement("code", $contact); my($contactCountry) = getElement("country", $contact); # # my($filed13G) = getAttribute("checkboxHeader", "filed13G", $header); my($paidFee) = getAttribute("checkboxHeader", "paidFee", $header); # HTMLize HEADER data $html .= "

$class

\n"; $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Type:$type
Sequence:$sequence
\n"; $html .= "

\n"; $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
Amendment Number:$amendmentNum
Issuer Name:$issuerName
Issuer Symbol:$issuerSymbol
Issuer Address:$issuerStreet
\n"; $html .= " $issuerCity, $issuerState $issuerZip
\n"; $html .= " $issuerCountry
Security Title:$securityTitle
CUSIP:$cusip
Event Date:$eventMonth $eventDay, $eventYear
Contact Name:$contactName
Contact Address:$contactStreet
\n"; $html .= " $contactCity, $contactState $contactZip
\n"; $html .= " $contactCountry
Filed 13G?:$filed13G
Paid Fee?:$paidFee
\n"; $html .= "

\n"; # # COVER # $html .= "

Cover Data

\n"; # my (@coverArr) = getElementArr("cover", $text); my $cover; foreach $cover (@coverArr) { # my($cusip) = getElement("cusip", $cover); # # my($filer) = getElementAll("filer", $cover); my($filerName) = getAttribute("filer", "fullName", $filer); my($filerIrsId) = getElement("irs-id", $filer); my($filerStreet) = getElement("street", $filer); my($filerCity) = getElement("city", $filer); my($filerState) = getElement("region", $filer); my($filerZip) = getElement("code", $filer); my($filerCountry) = getElement("country", $filer); # my($secOnly) = getElement("secOnly", $cover); # # my($fundSourceCat) = getAttribute("fundSource", "category", $cover); # my($citizenship) = getElement("citizenship", $cover); # # my($soleVote) = getAttribute("sharesOwned", "soleVote", $cover); my($sharedVote) = getAttribute("sharesOwned", "sharedVote", $cover); my($soleDispositive) = getAttribute("sharesOwned", "soleDispositive", $cover); my($sharedDispositive) = getAttribute("sharesOwned", "sharedDispositive", $cover); # # my($checkBoxGroup) = getAttribute("checkboxCover", "group", $cover); my($checkBoxDisc) = getAttribute("checkboxCover", "disclosure", $cover); my($checkBoxAgg) = getAttribute("checkboxCover", "aggregate", $cover); my($checkBoxRule) = getAttribute("checkboxCover", "checkRule", $cover); # my($aggregateAmount) = getElement("aggregateAmount", $cover); # my($classPercent) = getElement("classPercent", $cover); # my($personType) = getElement("personType", $cover); # # my(@roleCategoryArr) = getAttributeArr("role", "category", $personType); # my($notes) = getElement("notes", $personType); # HTMLize COVER data $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; my $roleCategory; foreach $roleCategory (@roleCategoryArr) { $html .= " \n"; $html .= " \n"; $html .= " \n"; } $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= "
CUSIP:$cusip
Filer Name:$filerName
Filer IRS Id:$filerIrsId
Filer Address:$filerStreet
\n"; $html .= " $filerCity, $filerState $filerZip
\n"; $html .= " $filerCountry
SEC Only:$secOnly
Fund Source Category:$fundSourceCat
Citizenship:$citizenship
Shares Owned Sole Vote:$soleVote
Shares Owned Shared Vote:$sharedVote
Shares Owned Sole Dispositive:$soleDispositive
Shares Owned Shared Dispositive:$sharedDispositive
Check Box Cover Group:$checkBoxGroup
Check Box Cover Disclosure:$checkBoxDisc
Check Box Cover Aggregate:$checkBoxAgg
Check Box Cover Rule:$checkBoxRule
Aggregate Amount:$aggregateAmount
Class Percent:$classPercent
Role Category:$roleCategory
Notes:$notes
\n"; $html .= "

\n"; } # # ITEMS # $html .= "

Items Data

\n"; # my ($items) = getElementArr("items", $text); # $securityTitle = getElement("securityTitle", $items); # # $issuer = getElementAll("issuer.b2", $items); $issuerName = getAttribute("issuer.b2", "name", $items); $issuerSymbol = getAttribute("issuer.b2", "symbol", $items); $issuerStreet = getElement("street", $issuer); $issuerCity = getElement("city", $issuer); $issuerState = getElement("region", $issuer); $issuerZip = getElement("code", $issuer); $issuerCountry = getElement("country", $issuer); # # my($filer) = getElementAll("filer", $items); my($filerName) = getAttribute("filer", "fullName", $filer); my($filerIrsId) = getElement("irs-id", $filer); my($filerStreet) = getElement("street", $filer); my($filerCity) = getElement("city", $filer); my($filerState) = getElement("region", $filer); my($filerZip) = getElement("code", $filer); my($filerCountry) = getElement("country", $filer); # # my($occupation) = getElementAll("occupation", $items); my($occDesc) = getAttribute("occupation", "description", $occupation); my($occBusName) = getAttribute("occupation", "businessName", $occupation); my($occPrinBus) = getAttribute("occupation", "principalBusiness", $occupation); # my($criminalRecord) = getElement("criminalRecord", $items); # my($civilRecord) = getElement("civilRecord", $items); # my($citizenship) = getElement("citizenship", $items); # $cusip = getElement("cusip", $items); # my($otherReceiver) = getElement("otherReceiver", $items); # # my($conSource) = getAttribute("considerationSource", "source", $items); my($conAmount) = getAttribute("considerationSource", "amount", $items); # my($purpose) = getElement("purpose", $items); # my($issuerInterest) = getElement("issuerInterest", $items); # # my($beneficiallyOwned) = getElementAll("beneficiallyOwned", $issuerInterest); my($benOwnSecurityTitle) = getElement("securityTitle", $beneficiallyOwned); my($benOwnAcqRight) = getAttribute("beneficiallyOwned", "acquireRight", $beneficiallyOwned); my($benOwnAggAmount) = getAttribute("beneficiallyOwned", "aggregateAmount", $beneficiallyOwned); my($benOwnPercentClass) = getAttribute("beneficiallyOwned","percentOfClass", $beneficiallyOwned); # my($solePower) = getElement("solePower", $issuerInterest); # # my($recentTransactions) = getElementAll("recentTransactions", $issuerInterest); my($recTranAmount) = getElement("amount", $recentTransactions); my($recTranName) = getAttribute("recentTransactions","fullName", $recentTransactions); my($recTranDay) = getAttribute("recentTransactions","day", $recentTransactions); my($recTranMonth) = getAttribute("recentTransactions","month", $recentTransactions); my($recTranYear) = getAttribute("recentTransactions","year", $recentTransactions); my($recTranAvePrice) = getAttribute("recentTransactions","averagePrice", $recentTransactions); my($recTranDetail) = getAttribute("recentTransactions","transactionDetail", $recentTransactions); # my($otherReceiverIssuer) = getElement("otherReceiver", $issuerInterest); # # my($ownCeasedCheck) = getAttribute("ownershipCeased","check", $issuerInterest); my($ownCeasedDay) = getAttribute("ownershipCeased","day", $issuerInterest); my($ownCeasedMonth) = getAttribute("ownershipCeased","month", $issuerInterest); my($ownCeasedYear) = getAttribute("ownershipCeased","year", $issuerInterest); # my($contracts) = getElement("contracts", $items); # # my($exhibitsName) = getAttribute("exhibits", "name", $items); my($exhibitsDesc) = getAttribute("exhibits", "description", $items); # # my($checkOptions) = getAttribute("roleCheck", "checkOptions", $items); # # my(@ownershipAmount) = getAttributeArr("ownership.b2", "amount", $items); my(@ownershipPercent) = getAttributeArr("ownership.b2", "percent", $items); my(@ownershipSoleVote) = getAttributeArr("ownership.b2", "soleVote", $items); my(@ownershipSharedVote) = getAttributeArr("ownership.b2", "sharedVote", $items); my(@ownershipSharedDisp) = getAttributeArr("ownership.b2", "sharedDispositive", $items); my(@ownershipSoleDisp) = getAttributeArr("ownership.b2", "soleDispositive", $items); # # $ownCeasedCheck = getAttribute("ownershipCeased","check", $items); $ownCeasedDay = getAttribute("ownershipCeased","day", $items); $ownCeasedMonth = getAttribute("ownershipCeased","month", $items); $ownCeasedYear = getAttribute("ownershipCeased","year", $items); # my($subsidiary) = getElement("subsidiary", $items); # # my($groupId) = getAttribute("groupID","id", $items); my($groupIdClass) = getAttribute("groupID","class", $items); # my($dissolution) = getElement("dissolution", $items); # # my($certificationRule) = getAttribute("certification","rule", $items); # HTMLize ITEMS data $html .= "\n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; my $cnt; for ($cnt = 0; $cnt < $#ownershipAmount; $cnt++) { $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; } $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; my $certification; # broken!!!!!!!! $html .= " \n"; $html .= " \n"; $html .= "
Security Title:$securityTitle
Issuer Name:$issuerName
Issuer Symbol:$issuerSymbol
Issuer Address:$issuerStreet
\n"; $html .= " $issuerCity, $issuerState $issuerZip
\n"; $html .= " $issuerCountry
Filer Name:$filerName
Filer IRS ID:$filerIrsId
Filer Address:$filerStreet
\n"; $html .= " $filerCity, $filerState $filerZip
\n"; $html .= " $filerCountry
Occupation Description:$occDesc
Occupation Business Name:$occBusName
Occupation Principal Business:$occPrinBus
Criminal Record:$criminalRecord
Civil Record:$civilRecord
Citizenship:$citizenship
CUSIP:$cusip
Other Receiver:$otherReceiver
Consideration Source:$conSource
Consideration Amount:$conAmount
Purpose:$purpose
Beneficially Owned Security Title:$benOwnSecurityTitle
Beneficially Owned Acquire Right:$benOwnAcqRight
Beneficially Owned Aggregate Amount:$benOwnAggAmount
Beneficially Owned Percent Class:$benOwnPercentClass
Sole Power:$solePower
Recent Transactions Amount:$recTranAmount
Recent Transactions Name:$recTranName
Recent Transactions Date:$recTranMonth $recTranDay, $recTranYear
Recent Transactions Average Price:$recTranAvePrice
Recent Transactions Detail:$recTranDetail
Other Receiver (Issuer):$otherReceiverIssuer
Owner Ceased Check:$ownCeasedCheck
Owner Ceased Date:$ownCeasedMonth $ownCeasedDay, $ownCeasedYear
Contracts:$contracts
Exhibits Name:$exhibitsName
Exhibits Description:$exhibitsDesc
Role Check Options:$checkOptions
Ownership
Ownership Amount:$ownershipAmount[$cnt]
Ownership Percent:$ownershipPercent[$cnt]
Ownership Sole Vote:$ownershipSoleVote[$cnt]
Ownership Shared Vote:$ownershipSharedVote[$cnt]
Ownership Shared Dispositive:$ownershipSharedDisp[$cnt]
Ownership Sole Dispositive:$ownershipSoleDisp[$cnt]
Ownership Ceased Check:$ownCeasedCheck
Ownership Ceased Date:$ownCeasedMonth $ownCeasedDay, $ownCeasedYear
Subsidiary:$subsidiary
Group ID:$groupId
Group ID Class:$groupIdClass
Dissolution:$dissolution
Certification:$certification
\n"; $html .= "

\n"; # # FOOTER # # my($footer) = getElement("footer", $text); my(@signatureArr) = getElementArr("signature", $footer); my($signatureDay) = getAttribute("signatureDate", "day", $footer); my($signatureMonth) = getAttribute("signatureDate", "month", $footer); my($signatureYear) = getAttribute("signatureDate", "year", $footer); my(@filerArr) = getAttributeArr("filer", "fullName", $footer); # HTMLize FOOTER data $html .= "\n"; my $signature; foreach $signature (@signatureArr) { $html .= " \n"; $html .= " \n"; $html .= " \n"; } $html .= " \n"; $html .= " \n"; $html .= " \n"; $html .= " \n"; foreach $filer (@filerArr) { $html .= " \n"; $html .= " \n"; $html .= " \n"; } $html .= "
Signature:$signature
Signature Date:$signatureMonth $signatureDay, $signatureYear
Filer:$filer
\n"; if ($debug > 1) { print STDERR "\n\n\n************* HTML **********\n\n$html\n\n"; } $html; } 1; =head1 NAME edgar-html.pl - EDGAR date routines =head1 PACKAGE EDGAR::HTML =head1 SYNOPSIS require edgar-html.pl; =head1 REQUIRES Perl, version 5.001 or higher, HTML::Template, and HTML::FromText. =head1 DESCRIPTION support to convert SEC EDGAR (edgardoc DTD format) XML documents to HTML =over 3 =head1 METHODS =head2 toHTML =item * generate HTML format edgardoc =item * HTML text is returned. =item example: my ($HTML) = &EDGAR::HTML::toHTML(\%edgardoc, $template, $templateVersion); =head2 generateSubmissionHeader =item * generate submission header information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateSubmissionHeader(\%submission, $tmpl, $templateVersion); =head2 generateTransformer =item * generate transformer information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateTransformer(\%submission, $tmpl, $templateVersion); =head2 generateRegistrants =item * generate registrant information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateRegistrant(\%submission, $tmpl, $templateVersion); =head2 generateDocuments =item * generate document information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateDocument(\%submission, $tmpl, $templateVersion); =head2 generateParsedEdgar =item * generate parsed EDGAR information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateParsedEdgar(\%submission, $tmpl); =head2 generateStamps =item * generate stamps information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateStamps(\@stamps, $tmpl); =head2 generateToC =item * generate table of contents information =item * The HTML template is updated. =item example: &EDGAR::HTML::generateToC(\%submission, $tmpl); =head2 getElementArr =item * obtains an element from an XML tag =item * An array of elements that are within the tag is returned. =item example: my(@elementData) = &EDGAR::HTML::getElementArr("elementName", $text); =head2 getElement =item * obtains an element from an XML tag =item * An element that is within a tag is returned. =item example: my($elementData) = &EDGAR::HTML::getElement("elementName", $text); =head2 getElementAll =item * obtains an element and attributes of an XML tag =item * An element and its attributes that are within the tag is returned. =item example: my($elementData) = &EDGAR::HTML::getElementAll("elementName", $text); =head2 getAttribute =item * obtains an attribute of an XML tag =item * An attributes value is returned. =item example: my($attrVal) = &EDGAR::HTML::getAttribute("elementName", "attributeName", $text); =head2 getAttributeArr =item * obtains an array of attribute values of an XML tag =item * An array of attribute values is returned. =item example: my(@attrVal) = &EDGAR::HTML::getAttributeArr("elementName", "attributeName", $text); =head2 toParagraphs =item * generates paragraph tags within the text =item * The string passed in is returned with HTML paragraph tags in places where it is believed they should be. =item example: my($parText) = &EDGAR::HTML::toParagraphs($text); =head2 edgarBeneficial1 =item * generates HTML from parsed edgar data for beneficial 1 forms =item * Beneficial 1 XML data is returned in HTML format. =item example: my($HTMLtext) = &EDGAR::HTML::edgarBeneficial1($xml); =head2 edgarBeneficial2 =item * generates HTML from parsed edgar data for beneficial 2 forms =item * Beneficial 2 XML data is returned in HTML format. =item example: my($HTMLtext) = &EDGAR::HTML::edgarBeneficial2($xml); =back =head1 COPYRIGHT Copyright 1999 Invisible Worlds. =cut