I've been working on some classes for extracting meaningful content from an
existing PDF file (in my case, I am primarily interested in extracting
text), and I thought I'd share the current classes (in attached zip file).

The classes work by using iText to get at the content bytes of a particular
page, then processing the content.

The content is parsed by the PDFContentStreamTokenizer class, which breaks
the stream up into either PDFContentOperator objects (which represent an
operator in the content stream) or String objects (which represent operands
on the rendering stack - i.e. inputs that the operators are supposed to
perform on).

Sub-classes of PDFContentOperatorProcessor are then created to implement
customized processing of the operator/operand groups.  Right now, there are
processors for:

- RawTextExtractor:  Retrieving all of the content in a single string,
unformatted
- SimpleFormattedTextExtractor:  Retrieving all of the content in a single
string with linebreaks in the appropriate places
- PhraseTextExtractor:  Retrieving all of the content in a single string
with each "phrase" (i.e. group of words that are put into the PDF in a
single operation) on a separate line

The PDFContentStreamProcessor class is used to tie it all together and make
it easy to use.  I have included a simple ProcessorExerciser class which
shows how to use each of the above extractors.


It should be pretty straightforward to create new extractors.  This could
even be used as the foundation for rendering the PDF in a Java UI.


As a last comment:  The SimpleFormattedTextExtractor is by no means 100%
solid.  Detecting line breaks is a bit tough, and I'm sure that I haven't
completely accounted for all of the coordinate transformations, etc... that
can happen in a PDF content stream.  It does appear to work on all of the
PDFs I've tested it with, though.


I'd love to get some feedback on the architecture, and any ideas you all
might have.

I hope it's OK to post a ZIP file...

Cheers,

Kevin


begin 666 itextextensions.zip
M4$L#!!0`" `(`-)%;2\```````````````!/````4$1&07-S96UB;&5R+W-R
M8R]C;VTO=')U;7!E=&EN8R]I=&5X=&5X=&5N<VEO;G,O0V]N=&5N=$]P97)A
M=&EO;E-U;6UA<FEZ97(N:F%V876234^#0!"&STO"[EMAIL PROTECTED];05H]H8E)CXL4V
MJ;>FARU.V[7L1W:7QH_TOSNPH-%J`K.P\[[O,Y =#^,(AC"[EMAIL PROTECTED];PJ(\P
MG69P.9E<M;VD3-L7>[EMAIL PROTECTED]>%!EWK2:>QQ'AI<'OD,HM<Q]T A2"(^O[:6<
MT,H5<11'XV'@W?+:[[6%`QZ%ZF/J325**"ON',RT(J.?&[3<DWU92\FM>$<+
M0IH*)34=+.[N?PBU75A=HG,4_='P6 MD1&PK45B'^1^0I(V7G5I_I]YH72%7
M8$)\3TO.!P#=/[EMAIL PROTECTED],-QRZ=(FE2W?G$>[EMAIL PROTECTED]>[WTM+,C
M_@@&D S2HC$PUM0M)2<D!P$W,"EHN>YB\PK5SN]I:S0*DS,FMB2&"U(&Z!_8
M008]X-36,"[EMAIL PROTECTED]"<;3]WBA_A96BCZBHUCTM55 YP.+K[\;1[1^
[EMAIL PROTECTED](,"``!02P,$% `([EMAIL PROTECTED]<`
M``!01$9!<W-E;6)L97(O<W)C+V-O;2]T<G5M<&5T:6YC+VET97AT97AT96YS
M:6]N<R]01$9#;VYT96YT3W!E<F%T;W(N:F%V866/04O#0!"%SPGD/PSQDL22
MM'I3A$)%\&(%O8F'[3JDVZ:[R^XD"*7_W=EL6D%A9F"9-]][VU19"A6L' K"
M+S :7LP`B\4,;N;SVW%7R')\P+OK#Q9I!L]:UF$5NLE2*^1>M C2'&J*&L4*
[EMAIL PROTECTED];*:'^?I5G:5-%O*7K:&@=[')0^8_I-IR3(3G@/KX]/*Z/YEM86G2#6
M'@,@L4X-'!7>R"[EMAIL PROTECTED]',3;A&<L+H<39!&7G_2<[EMAIL PROTECTED])*&M\K6Q\##A3M$I
MWD_B%OF^*([EMAIL PROTECTED]'[EMAIL 
PROTECTED]).%^OH"DN/"#LQB+H3NJW7FQU*NB(3&47Y-]O$_A7$
M/[EMAIL PROTECTED]<KCD"C_PSOT3F\0-02P<(J6(O+0P!``#0`0``4$L#
M!!0`" `(`-)%;2\```````````````!0````4$1&07-S96UB;&5R+W-R8R]C
M;VTO=')U;7!E=&EN8R]I=&5X=&5X=&5N<VEO;G,O4$1&0V]N=&5N=$]P97)A
M=&]R4')O8V5S<V]R+FIA=F%ED#UKPS 0AF<;_!]N3(+K).V8)9!2Z-)DZ%8Z
MG.5SK$;6&9V4%DK_>Q79"92")+BO1^][RT61PP)VCM!3`VSAA<^P7I=POUH]
MI-I,S5,`KR[T`_D2GJVJ+J7+71;[EMAIL PROTECTED]>7''AT[M*>O=*QHMK(I\B)?
M+L;_MAA\QPY.=-;[EMAIL PROTECTED]>1:5 2'QZ<=Q\CZ_4 ./;N#8T4B<?"[R+-X
M$B^[&[EMAIL PROTECTED]>[EMAIL PROTECTED](Z&^4P9%2, S=&@;DZC $T^J<7H[H,/^EOZ33*],
M*4<^.)M%EP2ZA6'[EMAIL PROTECTED]@#&\T'*J%%([EMAIL PROTECTED]&T)[
M15P=SOZ;OLDJ85]_D/)O[Y.H>=KI3Y'[EMAIL PROTECTED],8!``!02P,$
M% `([EMAIL PROTECTED]<W-E;6)L97(O<W)C+V-O
M;2]T<G5M<&5T:6YC+VET97AT97AT96YS:6]N<R]01$9#;VYT96YT4W1R96%M
M4')O8V5S<V]R+FIA=F%UDDUK&S$0AL]:V/\PN6F-62?MT11:TA8")0XTMY*#
M(D]BQ;N2D&;7:8/_>_6UL1LWL)[EMAIL PROTECTED]<.!>$:C(9K,\+%Q1P^
MG)]_3#DNF_0#MV[H+=(<KK1L8RK>B[JR0F[%(X(T?4M9HX)"$3ZG2WMEM%_6
M55VIWAI'\"1&T2K37JV^/4NT%/++TZ2V`_VD0-:_20ZDNO:+<^+W#^4I&2]F
MN9'/8J"-<;#%4>F);[COE 39">_AYNOW2Z,#5+&^<4:B]V')2UTQZ]08!G&B
MNC5;U.H/.K#">73+(^TK"%!4>[EMAIL PROTECTED]&G>',&^B.ER)D07(]%Q$BTSV+A,[EMAIL PROTECTED]
MWR1&EA%*F7=)>=#'POLXGJG2:-0:;+9?672"C//\X#'%#E,Q-GXW0!MG=AZ.
M=BRQK.Z?4);."U$.Y:[9;J,Z!,XG069O'Y&NP]%(L+QIX"PL';JN29Y,/4!9
MH+0GH26:!SB%+.K"\.LNFHL^SC]O1$LF;4)!8:R$98?"O09CL;/<9?MF,OP_
MDVF2R;S4:B8&YI &IXOG/KWV@)U'>/FGN%BO<V^E?I+N\SZQ<$K"ZR]02P<(
MN^3DO[ !``"4`P``4$L#!!0`" `(`--%;2\```````````````!.````4$1&
M07-S96UB;&5R+W-R8R]C;VTO=')U;7!E=&EN8R]I=&5X=&5X=&5N<VEO;G,O
M4$1&0V]N=&5N=%-T<F5A;51O:V5N:7IE<BYJ879AG59M;]LV$/YL`_X/EP"M
MI2R3[>[EMAIL PROTECTED]<=L'4?:/ELL98I0:2<MJ[_>[EMAIL PROTECTED]
M.=YS]_!XS."LUX4SN*F0*9Q!(>!=L8;[EMAIL PROTECTED];!;POJI7):ISN!-I
MHB']'?2Z)4N7;(&0%JM$61].'ESA9_,1DA="CGO=7I>ORJ)2\(FM6<*+Y.[^
M]G.*I2)\O ^*LE8319FM]L&'[EMAIL PROTECTED]>MW!F2WH-U:[EMAIL PROTECTED]:<Y3
M2',F)3R\_>.F$)2<[EMAIL PROTECTED]&"C8[3.4 `7!?1H047B]_K^9R<Y12N0> C
M^-8HUGX=^CK*HV11&#[>Z'[EMAIL PROTECTED]&[+<3S]AJF"!ZAW);CBB
MV :LBD<)GMJ&APL%:Y83S]#D.RV*')F &>9\A8JJNX8YRR4:90U39S `N>0E
M,/$%'C,Z8I!T_$C"#R9?I,)54M0J*4D+E8OH]([EMAIL PROTECTED]'ZBZI(2<?DF0S:+
MXGALXUE^PBIC-GE0W!PATM#)[EMAIL PROTECTED]<OR>,OS3;19!J)8]C?^K^SD--$HOH3
MQ4)ET=!FT6G_:)U0S-YZLI#&MY[%9!1HR.5]B153A?:F2X%-1W3X'*(P&NEO
M#Y[4I4Q861(>16G&[EMAIL PROTECTED]"5DWU9;*!.P.\MC)3-ZH886!KD;[0XDL'!P[)-
M2'Q)+8RY]=\"4N_ QN%>/DU3'0@)38.I#&TC'BW>+7PMV^KGUI>D[7_\V&_,
MCDU3W<J4E3C[P/*F#E=(N_=$'XO;]P--GE-F:^].>_04*K=]%L.KEJ)"55<"
M1)WGX\#]2;?040^&[EMAIL PROTECTED])S;%*#V3MOLZ**L:?R#;O1=<>#9
MX1%6+1^Y2C,CH9,]9=0%^ABNP"6B%V,/$SXD`JCRH2J E ^I`)KZT#2 YCXT
M#Z#(@Z(`B3TD=L@,[EMAIL PROTECTED];)7"_LS4"7U-#S.CX3
M?LQ[A/BYF,\$W09WRZ5[1UV[P"HI]5RF161B//[EMAIL PROTECTED]:;O4/.T=_;;3
M/GHN:9-;V[!F,=AIY]U![=HVMF/I6+-&!\[;(J\\Y'6 _.,A_P;(QD.V`?+"
M0U[TW3.[]:[L<+QW2?=?F*<QWE2W\4*88?::!N&;?C,U:>[EMAIL PROTECTED]:
M%Q:X?-UU,>.TKZV[QM,#QK.^-;3_JAPLPNNKH]GK%U*GXG[_ZOT>^<#HPC)Z
MEDL/[EMAIL PROTECTED]')-!_*[3M02P<(;-QQD:0#```'"P``4$L#!!0`" `(`--%
M;2\```````````````!(````4$1&07-S96UB;&5R+W-R8R]C;VTO=')U;7!E
M=&EN8R]I=&5X=&5X=&5N<VEO;G,O4&AR87-E5&5X=$5X=')A8W1O<BYJ879A
ME5)-2P,Q$#VGT/\P*NAN*=NJ1Q'$+_"[EMAIL PROTECTED]<UM3=9$VR59#^=R<[EMAIL PROTECTED]
MBK ;VGUOWKQYD]&@WX,[EMAIL PROTECTED]',+1>'P<L$SDX0],3%/5Z(9P
MHT3A(?^.^KV:BU>^0!"Z*ESD2&)(AQ_A459J94_ZO7YO-(C]SGCC7K2!5UQ)
MU<HTLU(*$"6W%NY?#+<XH?*K#V>X<$2655UBA<H1?'E]H15)N[L:#2?TWFB!
MUA+MTS=B,ZU+Y JD\B)P"G->6B03[,$9J1;GS7R.ACP'%<(5OL-W*,L]F9[@
MF9'I<))1EIQN\9CEOCU;!PM4&&[EMAIL PROTECTED])?\12_C+17QU\MD/U;:@A+ON)%R=6B
MN)LM4;CI4_YSGC:RG]TVY4!WNJT:U-SPRL;Y?6PI9Z)2N"V_6"")Q&B9G$.V
MD_:SOT^<`M\:VE*V>S[9S?,@Q+K]T;QA?6P-2)L$7[VU^&I+<;?\S>J62A^^
[EMAIL PROTECTED]/<8H-_.!1'21H'3KZPZ!KC.J&B!<DY9Z"HFB\
MGQ1U%KNGNK:%TY$<$UR'"TKG%U!+!PAW4'Z7J $``,8#``!02P,$% `([EMAIL PROTECTED]
MTT5M+P```````````````$<```!01$9!<W-E;6)L97(O<W)C+V-O;2]T<G5M
M<&5T:6YC+VET97AT97AT96YS:6]N<R]0<F]C97-S;W)%>&5R8VES97(N:F%V
M8<U56VO;,!1^=B#_X= GIQ2[72F#A<*VKH6^K*$)[&&,HBJGL5;;,I)R6^E_
MWY%EQ<YL9VPO&SCVB?2=[UP^7>+CX0".X4HA,S@'F<-GN8*SLQ-X<WIZ7LZ%
[EMAIL PROTECTED]:[EMAIL PROTECTED]:$[C->62G["\>[EMAIL 
PROTECTED]&G]D"@<LL,@XC""$,;LHGUT+F>CP<# <B
M*Z0R\)VM6"1D]'%K\(-2;'N;%TLS-91%-FZA;D2*[=';N^L-Q\(0=\?D'M]N
MVF:8RC5;"(QL:E$Q?XHF\Z=[9'-4)3(^=AUYSY8FD0J><25R7^CR,14<>,JT
MAHF2'[EMAIL PROTECTED]"EZ&@\ F"T1;)1V4? $1EF\B"2J6MG_8]!V5;(%)A(ZJ
M(;AL$K_:;#V9-LS09R7%'#(F\I!J%_GBZS=@:J$]E]HZ(^C('7?6)>2X[DK/
M#MOHX1%_%QO,BOCL_.+B_.W##+5YN"*-92KF=AW9C(]&(THSCBG<CCORUG29
M94R)'\1Z`'7/UC-2Z7IC%.-&'L3>2)4Q0[';'IWX2:*8QB[P*W!F> )A8X6!
MUR/ J*#.TMJB13\C/_1>]E5*8BVKC!(KZH73Y&!4,(F2:PW->&6P#C0Q>:O2
MJ;>.PBE(NM 6-(T=\468Y*Y Q0B[DSG<$3OOZ5:3Q)%<&E=PFM>(:('&1JRH
MPY%S^4WM?0KUEC^E79OVN+7Z< C\;QO2UX_VZN[MQ*_05O6=.^6_J[BYZWMK
MK1A==C1:.X&N35=V/_;O&E '&(V[2_E#PLFGF[T<&W,E55<;W-;WEQ(H]ZEV
MNQ\.JYO ZC!A)O$"/-*-2J<^=T')R[D[V *]7'2_UQ-3]H3EN5Z+&#0J`Z&K
MZ%W7=5B%<JYUO6YVOUIG597T(4.A][2CM599OH4Z+%LW]J<M/3\!4$L'"%F4
MMQ"<[EMAIL PROTECTED]@[EMAIL PROTECTED]" #316TO````````````````10```%!$1D%S
M<V5M8FQE<B]S<F,O8V]M+W1R=6UP971I;F,O:71E>'1E>'1E;G-I;VYS+U)A
M=U1E>'1%>'1R86-T;W(N:F%V895234L#,1 ]I]#_,"[EMAIL PROTECTED]
M$P]IG-;4W61-LE60_G<G'[M(*XJP&]J=-^^]>9/QL-^#(9P;Y Z?02NXT2LX
M.!C!X61R%&J9R,,?F)JFJM&-X%J)PI?\.^[W:BY>^0)!Z*IP$2,)(1U^A$=9
MJ94][O?ZO?$PZIWRQKUH`Z^XDJJE:6:E%"!*;BW<\_<I]5Y^.,.%(Z2LZA(K
M5,["W<75N5;$ZVYK-)RJ=T8+M)[EMAIL PROTECTED];0ND2N0RI/ "<QY:9$<L =GI%J<
M-?,Y&C(<6*BN\!V^E[+<@^D)AADY#B>Y9,GFIL$L]]IL'?2I*S; J<[EMAIL PROTECTED]
MF6>OCK_:0O9OJA$L^8H7)5>+XG:V1.$>G_+-8=J\-M6VZ4!WO"T;U-SPRL;Y
M?68I9()2LBV^6""1Q%R9G$.VDY8S&!"FP+>&5I3MGDUW\SP0L6YY-&_8'5L#
MTAK!=__8?/E#<[?Y[>X62A^^D4R7'[EMAIL PROTECTED]/DZ>XA1;]7W83Y5U
M$/2'0=<8U<T0[T>*/>[EMAIL PROTECTED]>DLBJ>^5L'I"(X!KL/EI/,+4$L'",3NJ1^F
M`0``OP,[EMAIL PROTECTED]" #316TO````````````````40```%!$1D%S<V5M
M8FQE<B]S<F,O8V]M+W1R=6UP971I;F,O:71E>'1E>'1E;G-I;VYS+U-I;7!L
M949O<FUA='1E9%1E>'1%>'1R86-T;W(N:F%V8>U66T_;,!1^#A+_X8Q)D+"2
MMMMX0DP(&!H/&TA4>V$\N,EI:TCLS'9ZV=3_OF,[2:M"H9-XVZ0V2G(N]G>Q
M3MK[VUNP#V<*F<$4I(!O<@S=;@O>=SH?7"Q,(O<`/57F!9H67(HDMB'[;V]O
M%2QY8$.$1.:Q\3F<,KC!J?L)S:701]M;VUOM?;_>"2O-2"IXP#$7=9NRG_$$
MDHQI#3<\+S*\D"IGAC;6HSZ?IT:QQ%"5B^4HC(;[EMAIL PROTECTED]<[EMAIL PROTECTED])!
MK2GMMUTQZ$N9(1/ A6T"[EMAIL PROTECTED];:37!C%!?#TW(P0$6;=UTH+G "RZ$PLLF<
M8M0GI=>4TW%H_$NFS7=4MO*@>[3T\HM4_%?SEGX.?$#HW940!Q7DY\"&D<41
MS-UZU,$7PXG&EPB/G^'F;>'OZD#XUZU:<,_&+,Z8&,97_7M,S.U=M JLYGYU
MM<?M0#9]ZVY0,,5R[?%;_BK!*)58K?/C(5(3KU' !Q"^J83>W:6<&'^6)'>X
M<]K;B2+7*&B,0'B=#X(Y(%D";/63Q9^?*&Y<[EMAIL PROTECTED];SVUEJT\N;-LXD9+3:
M(Y=$QA!53) UTD,8>JR1Y^#VXYT'V!16CGNQ\'!12)M92/:5F5',^CJL>AW4
M-HX^'4;0;L/$VJO,[EMAIL PROTECTED],,BX,1E"'\F?"D:HZ'X&R0B3!ZN(&2&<W1"[EMAIL PROTECTED]
MV1C(R(I/@8F4;EV*+)7/IX,("C-F^!BA%-SH&* WXAK(TKD&(V$BU0-YAA:;
[EMAIL PROTECTED](;>]QUBY:3Y7 4>UQ!=7)C5A0HTG#OA]BK,2^=S0KG4J#FOI;!
MA^:5=HVFRP*F:P5<-'QG;6"BBTPRXV5QMZO"=-8IVNQYPT;=_PJ_HL+G"X4'
[EMAIL PROTECTED])61=,-BKJK#ECK)3/;S"IF^B\[H1G.CHN#AK37MLC^PB*;&7-)
[EMAIL PROTECTED]"PO!)O<[EMAIL PROTECTED])^:=R3D),6L-1%
MNQV8<,]<@JY.V!F5<8%Q'#_&VMD`Y/U:D*N6G[L9:"\D8JE$,U9]__H3QX]N
M&M9V0E;#/_1+5'7U.D;Z9#_3Y^[;B:Y_`%!+!PBI&92F)P,``*H*``!02P$"
M% [EMAIL PROTECTED]" #216TOY0`UA%8!``"[EMAIL PROTECTED]&
M07-S96UB;&5R+W-R8R]C;VTO=')U;7!E=&EN8R]I=&5X=&5X=&5N<VEO;G,O
M0V]N=&5N=$]P97)A=&EO;E-U;6UA<FEZ97(N:F%V85!+`0(4`!0`" `(`-)%
M;2^I8B\M# $``- !``!'`````````````````-,!``!01$9!<W-E;6)L97(O
M<W)C+V-O;2]T<G5M<&5T:6YC+VET97AT97AT96YS:6]N<R]01$9#;VYT96YT
M3W!E<F%T;W(N:F%V85!+`0(4`!0`" `(`-)%;[EMAIL PROTECTED],8!``!0````
M`````````````%0#``!01$9!<W-E;6)L97(O<W)C+V-O;2]T<G5M<&5T:6YC
M+VET97AT97AT96YS:6]N<R]01$9#;VYT96YT3W!E<F%T;W)0<F]C97-S;W(N
M:F%V85!+`0(4`!0`" `(`-)%;2^[Y.2_L $``)0#``!.````````````````
[EMAIL PROTECTED]<W-E;6)L97(O<W)C+V-O;2]T<G5M<&5T:6YC+VET97AT97AT
M96YS:6]N<R]01$9#;VYT96YT4W1R96%M4')O8V5S<V]R+FIA=F%02P$"% `4
[EMAIL PROTECTED]" #316TO;-QQD:0#```'"[EMAIL PROTECTED]&07-S
M96UB;&5R+W-R8R]C;VTO=')U;7!E=&EN8R]I=&5X=&5X=&5N<VEO;G,O4$1&
M0V]N=&5N=%-T<F5A;51O:V5N:7IE<BYJ879A4$L!`A0`% `([EMAIL PROTECTED]
M?I>H`0``Q@,[EMAIL PROTECTED] L``%!$1D%S<V5M8FQE<B]S<F,O
M8V]M+W1R=6UP971I;F,O:71E>'1E>'1E;G-I;VYS+U!H<F%S951E>'1%>'1R
M86-T;W(N:F%V85!+`0(4`!0`" `(`--%;2]9E+<0G (``,<(``!'````````
M`````````%(-``!01$9!<W-E;6)L97(O<W)C+V-O;2]T<G5M<&5T:6YC+VET
M97AT97AT96YS:6]N<R]0<F]C97-S;W)%>&5R8VES97(N:F%V85!+`0(4`!0`
M" `(`--%;[EMAIL PROTECTED]&,0``!01$9!<W-E
M;6)L97(O<W)C+V-O;2]T<G5M<&5T:6YC+VET97AT97AT96YS:6]N<R]287=4
M97AT17AT<F%C=&]R+FIA=F%02P$"% [EMAIL PROTECTED]" #316TOJ1F4IB<#``"J"@``
[EMAIL PROTECTED]&07-S96UB;&5R+W-R8R]C;VTO=')U;7!E
M=&EN8R]I=&5X=&5X=&5N<VEO;G,O4VEM<&QE1F]R;6%T=&5D5&5X=$5X=')A
?8W1O<[EMAIL PROTECTED])``D`100``"(6````````
`
end




-------------------------------------------------------
This SF.Net email sponsored by: ApacheCon 2003,
16-19 November in Las Vegas. Learn firsthand the latest
developments in Apache, PHP, Perl, XML, Java, MySQL,
WebDAV, and more! http://www.apachecon.com/
_______________________________________________
iText-questions mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Reply via email to