001: // htmlFilterAbstractScraper.java
002: // ---------------------------
003: // (C) by Michael Peter Christen; mc@anomic.de
004: // first published on http://www.anomic.de
005: // Frankfurt, Germany, 2004
006: // last major change: 18.02.2004
007: //
008: // You agree that the Author(s) is (are) not responsible for cost,
009: // loss of data or any harm that may be caused by usage of this softare or
010: // this documentation. The usage of this software is on your own risk. The
011: // installation and usage (starting/running) of this software may allow other
012: // people or application to access your computer and any attached devices and
013: // is highly dependent on the configuration of the software which must be
014: // done by the user of the software;the author(s) is (are) also
015: // not responsible for proper configuration and usage of the software, even
016: // if provoked by documentation provided together with the software.
017: //
018: // THE SOFTWARE THAT FOLLOWS AS ART OF PROGRAMMING BELOW THIS SECTION
019: // IS PUBLISHED UNDER THE GPL AS DOCUMENTED IN THE FILE gpl.txt ASIDE THIS
020: // FILE AND AS IN http://www.gnu.org/licenses/gpl.txt
021: // ANY CHANGES TO THIS FILE ACCORDING TO THE GPL CAN BE DONE TO THE
022: // LINES THAT FOLLOWS THIS COPYRIGHT NOTICE HERE, BUT CHANGES MUST NOT
023: // BE DONE ABOVE OR INSIDE THE COPYRIGHT NOTICE. A RE-DISTRIBUTION
024: // MUST CONTAIN THE INTACT AND UNCHANGED COPYRIGHT NOTICE.
025: // CONTRIBUTIONS AND CHANGES TO THE PROGRAM CODE SHOULD BE MARKED AS SUCH.
026:
027: package de.anomic.htmlFilter;
028:
029: import java.util.HashMap;
030: import java.util.Properties;
031: import java.util.TreeSet;
032:
033: import de.anomic.server.serverCharBuffer;
034:
035: public abstract class htmlFilterAbstractScraper implements
036: htmlFilterScraper {
037:
038: public static final char lb = '<';
039: public static final char rb = '>';
040: public static final char sl = '/';
041:
042: private TreeSet<String> tags0;
043: private TreeSet<String> tags1;
044:
045: // define a translation table for html character codings
046: private static HashMap<String, String> trans = new HashMap<String, String>(
047: 300);
048: static {
049: trans.put(""", "\""); //Anführungszeichen oben
050: trans.put("&", "&"); //Ampersand-Zeichen, kaufmännisches Und
051: trans.put("<", "<"); //öffnende spitze Klammer
052: trans.put(">", ">"); //schließende spitze Klammer
053: trans.put(" ", " "); //Erzwungenes Leerzeichen
054: trans.put("¡", "!"); //umgekehrtes Ausrufezeichen
055: trans.put("¢", " cent "); //Cent-Zeichen
056: trans.put("£", " pound "); //Pfund-Zeichen
057: trans.put("¤", " currency "); //Währungs-Zeichen
058: trans.put("¥", " yen "); //Yen-Zeichen
059: trans.put("¦", " "); //durchbrochener Strich
060: trans.put("§", " paragraph "); //Paragraph-Zeichen
061: trans.put("¨", " "); //Pünktchen oben
062: trans.put("©", " copyright "); //Copyright-Zeichen
063: trans.put("ª", " "); //Ordinal-Zeichen weiblich
064: trans.put("«", " "); //angewinkelte Anführungszeichen links
065: trans.put("¬", " not "); //Verneinungs-Zeichen
066: trans.put("­", "-"); //kurzer Trennstrich
067: trans.put("®", " trademark "); //Registriermarke-Zeichen
068: trans.put("¯", " "); //Überstrich
069: trans.put("°", " degree "); //Grad-Zeichen
070: trans.put("±", " +/- "); //Plusminus-Zeichen
071: trans.put("²", " square "); //Hoch-2-Zeichen
072: trans.put("³", " 3 "); //Hoch-3-Zeichen
073: trans.put("´", " "); //Acute-Zeichen
074: trans.put("µ", " micro "); //Mikro-Zeichen
075: trans.put("¶", " paragraph "); //Absatz-Zeichen
076: trans.put("·", " "); //Mittelpunkt
077: trans.put("¸", " "); //Häkchen unten
078: trans.put("¹", " "); //Hoch-1-Zeichen
079: trans.put("º", " degree "); //Ordinal-Zeichen männlich
080: trans.put("»", " "); //angewinkelte Anführungszeichen rechts
081: trans.put("¼", " quarter "); //ein Viertel
082: trans.put("½", " half "); //ein Halb
083: trans.put("¾", " 3/4 "); //drei Viertel
084: trans.put("¿", "?"); //umgekehrtes Fragezeichen
085: trans.put("À", "A"); //A mit Accent grave
086: trans.put("Á", "A"); //A mit Accent acute
087: trans.put("Â", "A"); //A mit Circumflex
088: trans.put("Ã", "A"); //A mit Tilde
089: trans.put("Ä", "Ae"); //A Umlaut
090: trans.put("Å", "A"); //A mit Ring
091: trans.put("Æ", "A"); //A mit legiertem E
092: trans.put("Ç", "C"); //C mit Häkchen
093: trans.put("È", "E"); //E mit Accent grave
094: trans.put("É", "E"); //E mit Accent acute
095: trans.put("Ê", "E"); //E mit Circumflex
096: trans.put("Ë", "E"); //E Umlaut
097: trans.put("Ì", "I"); //I mit Accent grave
098: trans.put("Í", "I"); //I mit Accent acute
099: trans.put("Î", "I"); //I mit Circumflex
100: trans.put("Ï", "I"); //I Umlaut
101: trans.put("Ð", "D"); //Eth (isländisch)
102: trans.put("Ñ", "N"); //N mit Tilde
103: trans.put("Ò", "O"); //O mit Accent grave
104: trans.put("Ó", "O"); //O mit Accent acute
105: trans.put("Ô", "O"); //O mit Circumflex
106: trans.put("Õ", "O"); //O mit Tilde
107: trans.put("Ö", "Oe"); //O Umlaut
108: trans.put("×", " times "); //Mal-Zeichen
109: trans.put("Ø", "O"); //O mit Schrägstrich
110: trans.put("Ù", "U"); //U mit Accent grave
111: trans.put("Ú", "U"); //U mit Accent acute
112: trans.put("Û", "U"); //U mit Circumflex
113: trans.put("Ü", "Ue"); //U Umlaut
114: trans.put("Ý", "Y"); //Y mit Accent acute
115: trans.put("Þ", "P"); //THORN (isländisch)
116: trans.put("ß", "ss"); //scharfes S
117: trans.put("à", "a"); //a mit Accent grave
118: trans.put("á", "a"); //a mit Accent acute
119: trans.put("â", "a"); //a mit Circumflex
120: trans.put("ã", "a"); //a mit Tilde
121: trans.put("ä", "ae"); //a Umlaut
122: trans.put("å", "a"); //a mit Ring
123: trans.put("æ", "a"); //a mit legiertem e
124: trans.put("ç", "c"); //c mit Häkchen
125: trans.put("è", "e"); //e mit Accent grave
126: trans.put("é", "e"); //e mit Accent acute
127: trans.put("ê", "e"); //e mit Circumflex
128: trans.put("ë", "e"); //e Umlaut
129: trans.put("ì", "i"); //i mit Accent grave
130: trans.put("í", "i"); //i mit Accent acute
131: trans.put("î", "i"); //i mit Circumflex
132: trans.put("ï", "i"); //i Umlaut
133: trans.put("ð", "d"); //eth (isländisch)
134: trans.put("ñ", "n"); //n mit Tilde
135: trans.put("ò", "o"); //o mit Accent grave
136: trans.put("ó", "o"); //o mit Accent acute
137: trans.put("ô", "o"); //o mit Circumflex
138: trans.put("õ", "o"); //o mit Tilde
139: trans.put("ö", "oe"); //o Umlaut
140: trans.put("÷", "%"); //Divisions-Zeichen
141: trans.put("ø", "o"); //o mit Schrägstrich
142: trans.put("ù", "u"); //u mit Accent grave
143: trans.put("ú", "u"); //u mit Accent acute
144: trans.put("û", "u"); //u mit Circumflex
145: trans.put("ü", "ue"); //u Umlaut
146: trans.put("ý", "y"); //y mit Accent acute
147: trans.put("þ", "p"); //thorn (isländisch)
148: trans.put("ÿ", "y"); //y Umlaut
149: trans.put("Α", " Alpha "); //Alpha groß
150: trans.put("α", " alpha "); //alpha klein
151: trans.put("Β", " Beta "); //Beta groß
152: trans.put("β", " beta "); //beta klein
153: trans.put("Γ", " Gamma "); //Gamma groß
154: trans.put("γ", " gamma "); //gamma klein
155: trans.put("Δ", " Delta "); //Delta groß
156: trans.put("δ", " delta "); //delta klein
157: trans.put("Ε", " Epsilon "); //Epsilon groß
158: trans.put("ε", " epsilon "); //epsilon klein
159: trans.put("Ζ", " Zeta "); //Zeta groß
160: trans.put("ζ", " zeta "); //zeta klein
161: trans.put("Η", " Eta "); //Eta groß
162: trans.put("η", " eta "); //eta klein
163: trans.put("Θ", " Theta "); //Theta groß
164: trans.put("θ", " theta "); //theta klein
165: trans.put("Ι", " Iota "); //Iota groß
166: trans.put("ι", " iota "); //iota klein
167: trans.put("Κ", " Kappa "); //Kappa groß
168: trans.put("κ", " kappa "); //kappa klein
169: trans.put("Λ", " Lambda "); //Lambda groß
170: trans.put("λ", " lambda "); //lambda klein
171: trans.put("Μ", " Mu "); //Mu groß
172: trans.put("μ", " mu "); //mu klein
173: trans.put("Ν", " Nu "); //Nu groß
174: trans.put("ν", " nu "); //nu klein
175: trans.put("Ξ", " Xi "); //Xi groß
176: trans.put("ξ", " xi "); //xi klein
177: trans.put("Ο", " Omicron "); //Omicron groß
178: trans.put("ο", " omicron "); //omicron klein
179: trans.put("Π", " Pi "); //Pi groß
180: trans.put("π", " pi "); //pi klein
181: trans.put("Ρ", " Rho "); //Rho groß
182: trans.put("ρ", " rho "); //rho klein
183: trans.put("Σ", " Sigma "); //Sigma groß
184: trans.put("ς", " sigma "); //sigmaf klein
185: trans.put("σ", " sigma "); //sigma klein
186: trans.put("Τ", " Tau "); //Tau groß
187: trans.put("τ", " tau "); //tau klein
188: trans.put("Υ", " Ypsilon "); //Upsilon groß
189: trans.put("υ", " ypsilon "); //upsilon klein
190: trans.put("Φ", " Phi "); //Phi groß
191: trans.put("φ", " phi "); //phi klein
192: trans.put("Χ", " Chi "); //Chi groß
193: trans.put("χ", " chi "); //chi klein
194: trans.put("Ψ", " Psi "); //Psi groß
195: trans.put("ψ", " psi "); //psi klein
196: trans.put("Ω", " Omega "); //Omega groß
197: trans.put("ω", " omega "); //omega klein
198: trans.put("ϑ", " theta "); //theta Symbol
199: trans.put("ϒ", " ypsilon "); //upsilon mit Haken
200: trans.put("ϖ", " pi "); //pi Symbol
201: trans.put("∀", " for all "); //für alle
202: trans.put("∂", " part of "); //teilweise
203: trans.put("∃", " exists "); //existiert
204: trans.put("∅", " null "); //leer
205: trans.put("∇", " nabla "); //nabla
206: trans.put("∈", " element of "); //Element von
207: trans.put("∉", " not element of "); //kein Element von
208: trans.put("∋", " contains "); //enthält als Element
209: trans.put("∏", " product "); //Produkt
210: trans.put("∑", " sum "); //Summe
211: trans.put("−", " minus "); //minus
212: trans.put("∗", " times "); //Asterisk
213: trans.put("√", " sqare root "); //Quadratwurzel
214: trans.put("∝", " proportional to "); //proportional zu
215: trans.put("∞", " unlimited "); //unendlich
216: trans.put("∠", " angle "); //Winkel
217: trans.put("∧", " and "); //und
218: trans.put("∨", " or "); //oder
219: trans.put("∩", " "); //Schnittpunkt
220: trans.put("∪", " unity "); //Einheit
221: trans.put("∫", " integral "); //Integral
222: trans.put("∴", " cause "); //deshalb
223: trans.put("∼", " similar to "); //ähnlich wie
224: trans.put("≅", " equal "); //annähernd gleich
225: trans.put("≈", " equal "); //beinahe gleich
226: trans.put("≠", " not equal "); //ungleich
227: trans.put("≡", " identical "); //identisch mit
228: trans.put("≤", " smaller or equal than "); //kleiner gleich
229: trans.put("≥", " greater or equal than "); //größer gleich
230: trans.put("⊂", " subset of "); //Untermenge von
231: trans.put("⊃", " superset of "); //Obermenge von
232: trans.put("⊄", " not subset of "); //keine Untermenge von
233: trans.put("⊆", ""); //Untermenge von oder gleich mit
234: trans.put("⊇", ""); //Obermenge von oder gleich mit
235: trans.put("⊕", ""); //Direktsumme
236: trans.put("⊗", ""); //Vektorprodukt
237: trans.put("⊥", ""); //senkrecht zu
238: trans.put("⋅", ""); //Punkt-Operator
239: trans.put("◊", ""); //Raute
240: trans.put("⌈", ""); //links oben
241: trans.put("⌉", ""); //rechts oben
242: trans.put("⌊", ""); //links unten
243: trans.put("⌋", ""); //rechts unten
244: trans.put("⟨", ""); //spitze Klammer links
245: trans.put("⟩", ""); //spitze Klammer rechts
246: trans.put("←", ""); //Pfeil links
247: trans.put("↑", ""); //Pfeil oben
248: trans.put("→", ""); //Pfeil rechts
249: trans.put("↓", ""); //Pfeil unten
250: trans.put("↔", ""); //Pfeil links/rechts
251: trans.put("↵", ""); //Pfeil unten-Knick-links
252: trans.put("⇐", ""); //Doppelpfeil links
253: trans.put("⇑", ""); //Doppelpfeil oben
254: trans.put("⇒", ""); //Doppelpfeil rechts
255: trans.put("⇓", ""); //Doppelpfeil unten
256: trans.put("⇔", ""); //Doppelpfeil links/rechts
257: trans.put("•", ""); //Bullet-Zeichen
258: trans.put("…", ""); //Horizontale Ellipse
259: trans.put("′", ""); //Minutenzeichen
260: trans.put("‾", ""); //Überstrich
261: trans.put("⁄", ""); //Bruchstrich
262: trans.put("℘", ""); //Weierstrass p
263: trans.put("ℑ", ""); //Zeichen für "imaginär"
264: trans.put("ℜ", ""); //Zeichen für "real"
265: trans.put("™", ""); //Trademark-Zeichen
266: trans.put("€", ""); //Euro-Zeichen
267: trans.put("ℵ", ""); //Alef-Symbol
268: trans.put("♠", ""); //Pik-Zeichen
269: trans.put("♣", ""); //Kreuz-Zeichen
270: trans.put("♥", ""); //Herz-Zeichen
271: trans.put("♦", ""); //Karo-Zeichen
272: trans.put(" ", ""); //Leerzeichen Breite n
273: trans.put(" ", ""); //Leerzeichen Breite m
274: trans.put(" ", ""); //Schmales Leerzeichen
275: trans.put("‌", ""); //null breiter Nichtverbinder
276: trans.put("‍", ""); //null breiter Verbinder
277: trans.put("‎", ""); //links-nach-rechts-Zeichen
278: trans.put("‏", ""); //rechts-nach-links-Zeichen
279: trans.put("–", ""); //Gedankenstrich Breite n
280: trans.put("—", ""); //Gedankenstrich Breite m
281: trans.put("‘", ""); //einfaches Anführungszeichen links
282: trans.put("’", ""); //einfaches Anführungszeichen rechts
283: trans.put("‚", ""); //einfaches low-9-Zeichen
284: trans.put("“", ""); //doppeltes Anführungszeichen links
285: trans.put("”", ""); //doppeltes Anführungszeichen rechts
286: trans.put("„", ""); //doppeltes low-9-Zeichen rechts
287: trans.put("†", ""); //Kreuz
288: trans.put("‡", ""); //Doppelkreuz
289: trans.put("‰", ""); //zu tausend
290: trans.put("‹", ""); //angewinkeltes einzelnes Anf.zeichen links
291: trans.put("›", ""); //angewinkeltes einzelnes Anf.zeichen rechts
292: }
293:
294: public htmlFilterAbstractScraper(TreeSet<String> tags0,
295: TreeSet<String> tags1) {
296: this .tags0 = tags0;
297: this .tags1 = tags1;
298: }
299:
300: public boolean isTag0(String tag) {
301: return (tags0 != null) && (tags0.contains(tag));
302: }
303:
304: public boolean isTag1(String tag) {
305: return (tags1 != null) && (tags1.contains(tag));
306: }
307:
308: //the 'missing' method that shall be implemented:
309: public abstract void scrapeText(char[] text, String insideTag);
310:
311: // the other methods must take into account to construct the return value correctly
312: public abstract void scrapeTag0(String tagname, Properties tagopts);
313:
314: public abstract void scrapeTag1(String tagname, Properties tagopts,
315: char[] text);
316:
317: // string conversions
318: private static String code_iso8859s(char c) {
319: switch (c) {
320:
321: // german umlaute and ligaturen
322: case 0xc4:
323: return "AE";
324: case 0xd6:
325: return "OE";
326: case 0xdc:
327: return "UE";
328: case 0xe4:
329: return "ae";
330: case 0xf6:
331: return "oe";
332: case 0xfc:
333: return "ue";
334: case 0xdf:
335: return "ss";
336:
337: // accent on letters; i.e. french characters
338: case 0xc0:
339: case 0xc1:
340: case 0xc2:
341: case 0xc3:
342: case 0xc5:
343: return "A";
344: case 0xc6:
345: return "AE";
346: case 0xc7:
347: return "C";
348: case 0xc8:
349: case 0xc9:
350: case 0xca:
351: return "E";
352: case 0xcc:
353: case 0xcd:
354: case 0xce:
355: case 0xcf:
356: return "I";
357: case 0xd0:
358: return "D";
359: case 0xd1:
360: return "N";
361: case 0xd2:
362: case 0xd3:
363: case 0xd4:
364: case 0xd5:
365: case 0xd8:
366: return "O";
367: case 0xd7:
368: return "x";
369: case 0xd9:
370: case 0xda:
371: case 0xdb:
372: return "U";
373: case 0xdd:
374: return "Y";
375: case 0xde:
376: return "p";
377:
378: case 0xe0:
379: case 0xe1:
380: case 0xe2:
381: case 0xe3:
382: case 0xe5:
383: return "a";
384: case 0xe6:
385: return "ae";
386: case 0xe7:
387: return "c";
388: case 0xe8:
389: case 0xe9:
390: case 0xea:
391: return "e";
392: case 0xec:
393: case 0xed:
394: case 0xee:
395: case 0xef:
396: return "i";
397: case 0xf0:
398: return "d";
399: case 0xf1:
400: return "n";
401: case 0xf2:
402: case 0xf3:
403: case 0xf4:
404: case 0xf5:
405: case 0xf8:
406: return "o";
407: case 0xf7:
408: return "%";
409: case 0xf9:
410: case 0xfa:
411: case 0xfb:
412: return "u";
413: case 0xfd:
414: case 0xff:
415: return "y";
416: case 0xfe:
417: return "p";
418:
419: // special characters
420: case 0xa4:
421: return " euro ";
422: default:
423: return null;
424: }
425: }
426:
427: public static serverCharBuffer convertUmlaute(serverCharBuffer bb) {
428: if (bb.length() == 0)
429: return bb;
430:
431: serverCharBuffer t = new serverCharBuffer(bb.length() + 20);
432: char c;
433: for (int i = 0; i < bb.length(); i++) {
434: c = bb.charAt(i);
435: String z = code_iso8859s(c);
436: if (z == null)
437: t.append((int) c);
438: else
439: t.append(z);
440: }
441: return t;
442:
443: // serverByteBuffer t = new serverByteBuffer(bb.length() + 20);
444: // int b0, b1, b2;
445: // String z;
446: // int i = 0;
447: // while (i < bb.length()) {
448: // b0 = bb.byteAt(i) & 0xff;
449: // // check utf-8 encoding
450: // if ((b0 < 128) || (i + 1 == bb.length())) {
451: // t.append(b0);
452: // i++;
453: // } else {
454: // b1 = bb.byteAt(i + 1) & 0xff;
455: // if (b1 > 0x3f) {
456: // z = code_iso8859s(b0);
457: // i++;
458: // } else if ((b0 > 0xbf) && (b0 < 0xe0)) {
459: // z = code_iso8859s(((b0 & 0x1f) << 0x6) | (b1 & 0x3f));
460: // i += 2;
461: // } else {
462: // if (i + 2 >= bb.length()) {
463: // z = null;
464: // i++;
465: // } else {
466: // b2 = bb.byteAt(i + 2) & 0xff;
467: // if (b2 > 0x3f) {
468: // z = code_iso8859s(b0);
469: // i++;
470: // } else {
471: // z = code_iso8859s(((b0 & 0xf) << 0xc) | ((b1 & 0x3f) << 0x6) | (b2 & 0x3f));
472: // i += 3;
473: // }
474: // }
475: // }
476: // if (z == null) t.append(b0); else t.append(z);
477: // }
478: // }
479: // return t;
480: }
481:
482: private static char[] transscript(char[] code) {
483: String t = (String) trans.get(new String(code));
484: if (t == null)
485: return new char[0];
486: return t.toCharArray();
487: }
488:
489: protected static serverCharBuffer transscriptAll(serverCharBuffer bb) {
490: int p0 = 0, p1;
491: char[] t;
492: while ((p0 = bb.indexOf('&', p0)) >= 0) {
493: p1 = bb.indexOf(';', p0);
494: if (p1 >= 0) {
495: t = transscript(bb.getChars(p0, p1 + 1));
496: bb = new serverCharBuffer(bb.getChars(0, p0), bb
497: .length()
498: + p0 - p1 + t.length).append(t).append(
499: bb.getChars(p1 + 1));
500: } else {
501: bb = new serverCharBuffer(bb.getChars(0, p0), bb
502: .length()).append(bb.getChars(p0 + 1));
503: }
504: }
505: t = null;
506: return bb;
507: }
508:
509: protected static serverCharBuffer stripAllTags(serverCharBuffer bb) {
510: int p0 = 0, p1;
511: while ((p0 = bb.indexOf(lb, p0)) >= 0) {
512: p1 = bb.indexOf(rb, p0);
513: if (p1 >= 0) {
514: bb = ((serverCharBuffer) new serverCharBuffer(bb
515: .getChars(0, p0), bb.length() + p0 - p1 + 1)
516: .trim().append(32))
517: .append(new serverCharBuffer(bb
518: .getChars(p1 + 1)).trim());
519: } else {
520: bb = new serverCharBuffer(bb.getChars(0, p0), bb
521: .length()).trim().append(
522: new serverCharBuffer(bb.getChars(p0 + 1))
523: .trim());
524: }
525: }
526: return bb.trim();
527: }
528:
529: public static serverCharBuffer stripAll(serverCharBuffer bb) {
530: //return stripAllTags(s);
531: return convertUmlaute(transscriptAll(stripAllTags(bb)));
532: }
533:
534: public void close() {
535: // free resources
536: tags0 = null;
537: tags1 = null;
538: }
539:
540: public void finalize() {
541: close();
542: }
543:
544: }
|