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+�J`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