001: /*
002: * $Id: SAXmyHtmlHandler.java 2748 2007-05-12 15:11:48Z blowagie $
003: * $Name$
004: *
005: * Copyright 2001, 2002 by Bruno Lowagie.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.html;
052:
053: import java.util.HashMap;
054: import java.util.Properties;
055:
056: import org.xml.sax.Attributes;
057:
058: import com.lowagie.text.DocListener;
059: import com.lowagie.text.DocumentException;
060: import com.lowagie.text.Element;
061: import com.lowagie.text.ElementTags;
062: import com.lowagie.text.ExceptionConverter;
063: import com.lowagie.text.pdf.BaseFont;
064: import com.lowagie.text.xml.SAXiTextHandler;
065: import com.lowagie.text.xml.XmlPeer;
066:
067: /**
068: * The <CODE>Tags</CODE>-class maps several XHTML-tags to iText-objects.
069: */
070:
071: public class SAXmyHtmlHandler extends SAXiTextHandler // SAXmyHandler
072: {
073:
074: /** These are the properties of the body section. */
075: private Properties bodyAttributes = new Properties();
076:
077: /** This is the status of the table border. */
078: private boolean tableBorder = false;
079:
080: /**
081: * Constructs a new SAXiTextHandler that will translate all the events
082: * triggered by the parser to actions on the <CODE>Document</CODE>-object.
083: *
084: * @param document
085: * this is the document on which events must be triggered
086: */
087:
088: public SAXmyHtmlHandler(DocListener document) {
089: super (document, new HtmlTagMap());
090: }
091:
092: /**
093: * Constructs a new SAXiTextHandler that will translate all the events
094: * triggered by the parser to actions on the <CODE>Document</CODE>-object.
095: *
096: * @param document
097: * this is the document on which events must be triggered
098: * @param bf
099: */
100:
101: public SAXmyHtmlHandler(DocListener document, BaseFont bf) {
102: super (document, new HtmlTagMap(), bf);
103: }
104:
105: /**
106: * Constructs a new SAXiTextHandler that will translate all the events
107: * triggered by the parser to actions on the <CODE>Document</CODE>-object.
108: *
109: * @param document
110: * this is the document on which events must be triggered
111: * @param htmlTags
112: * a tagmap translating HTML tags to iText tags
113: */
114:
115: public SAXmyHtmlHandler(DocListener document, HashMap htmlTags) {
116: super (document, htmlTags);
117: }
118:
119: /**
120: * This method gets called when a start tag is encountered.
121: *
122: * @param uri
123: * the Uniform Resource Identifier
124: * @param lname
125: * the local name (without prefix), or the empty string if
126: * Namespace processing is not being performed.
127: * @param name
128: * the name of the tag that is encountered
129: * @param attrs
130: * the list of attributes
131: */
132:
133: public void startElement(String uri, String lname, String name,
134: Attributes attrs) {
135: // System.err.println("Start: " + name);
136:
137: // super.handleStartingTags is replaced with handleStartingTags
138: // suggestion by Vu Ngoc Tan/Hop
139: name = name.toLowerCase();
140: if (((HtmlTagMap) myTags).isHtml(name)) {
141: // we do nothing
142: return;
143: }
144: if (((HtmlTagMap) myTags).isHead(name)) {
145: // we do nothing
146: return;
147: }
148: if (((HtmlTagMap) myTags).isTitle(name)) {
149: // we do nothing
150: return;
151: }
152: if (((HtmlTagMap) myTags).isMeta(name)) {
153: // we look if we can change the body attributes
154: String meta = null;
155: String content = null;
156: if (attrs != null) {
157: for (int i = 0; i < attrs.getLength(); i++) {
158: String attribute = attrs.getQName(i);
159: if (attribute.equalsIgnoreCase(HtmlTags.CONTENT))
160: content = attrs.getValue(i);
161: else if (attribute.equalsIgnoreCase(HtmlTags.NAME))
162: meta = attrs.getValue(i);
163: }
164: }
165: if (meta != null && content != null) {
166: bodyAttributes.put(meta, content);
167: }
168: return;
169: }
170: if (((HtmlTagMap) myTags).isLink(name)) {
171: // we do nothing for the moment, in a later version we could extract
172: // the style sheet
173: return;
174: }
175: if (((HtmlTagMap) myTags).isBody(name)) {
176: // maybe we could extract some info about the document: color,
177: // margins,...
178: // but that's for a later version...
179: XmlPeer peer = new XmlPeer(ElementTags.ITEXT, name);
180: peer.addAlias(ElementTags.TOP, HtmlTags.TOPMARGIN);
181: peer.addAlias(ElementTags.BOTTOM, HtmlTags.BOTTOMMARGIN);
182: peer.addAlias(ElementTags.RIGHT, HtmlTags.RIGHTMARGIN);
183: peer.addAlias(ElementTags.LEFT, HtmlTags.LEFTMARGIN);
184: bodyAttributes.putAll(peer.getAttributes(attrs));
185: handleStartingTags(peer.getTag(), bodyAttributes);
186: return;
187: }
188: if (myTags.containsKey(name)) {
189: XmlPeer peer = (XmlPeer) myTags.get(name);
190: if (ElementTags.TABLE.equals(peer.getTag())
191: || ElementTags.CELL.equals(peer.getTag())) {
192: Properties p = peer.getAttributes(attrs);
193: String value;
194: if (ElementTags.TABLE.equals(peer.getTag())
195: && (value = p
196: .getProperty(ElementTags.BORDERWIDTH)) != null) {
197: if (Float.parseFloat(value + "f") > 0) {
198: tableBorder = true;
199: }
200: }
201: if (tableBorder) {
202: p.put(ElementTags.LEFT, String.valueOf(true));
203: p.put(ElementTags.RIGHT, String.valueOf(true));
204: p.put(ElementTags.TOP, String.valueOf(true));
205: p.put(ElementTags.BOTTOM, String.valueOf(true));
206: }
207: handleStartingTags(peer.getTag(), p);
208: return;
209: }
210: handleStartingTags(peer.getTag(), peer.getAttributes(attrs));
211: return;
212: }
213: Properties attributes = new Properties();
214: if (attrs != null) {
215: for (int i = 0; i < attrs.getLength(); i++) {
216: String attribute = attrs.getQName(i).toLowerCase();
217: attributes.setProperty(attribute, attrs.getValue(i)
218: .toLowerCase());
219: }
220: }
221: handleStartingTags(name, attributes);
222: }
223:
224: /**
225: * This method gets called when an end tag is encountered.
226: *
227: * @param uri
228: * the Uniform Resource Identifier
229: * @param lname
230: * the local name (without prefix), or the empty string if
231: * Namespace processing is not being performed.
232: * @param name
233: * the name of the tag that ends
234: */
235:
236: public void endElement(String uri, String lname, String name) {
237: // System.err.println("End: " + name);
238: name = name.toLowerCase();
239: if (ElementTags.PARAGRAPH.equals(name)) {
240: try {
241: document.add((Element) stack.pop());
242: return;
243: } catch (DocumentException e) {
244: throw new ExceptionConverter(e);
245: }
246: }
247: if (((HtmlTagMap) myTags).isHead(name)) {
248: // we do nothing
249: return;
250: }
251: if (((HtmlTagMap) myTags).isTitle(name)) {
252: if (currentChunk != null) {
253: bodyAttributes.put(ElementTags.TITLE, currentChunk
254: .getContent());
255: }
256: return;
257: }
258: if (((HtmlTagMap) myTags).isMeta(name)) {
259: // we do nothing
260: return;
261: }
262: if (((HtmlTagMap) myTags).isLink(name)) {
263: // we do nothing
264: return;
265: }
266: if (((HtmlTagMap) myTags).isBody(name)) {
267: // we do nothing
268: return;
269: }
270: if (myTags.containsKey(name)) {
271: XmlPeer peer = (XmlPeer) myTags.get(name);
272: if (ElementTags.TABLE.equals(peer.getTag())) {
273: tableBorder = false;
274: }
275: super .handleEndingTags(peer.getTag());
276: return;
277: }
278: // super.handleEndingTags is replaced with handleEndingTags
279: // suggestion by Ken Auer
280: handleEndingTags(name);
281: }
282: }
|