1 | /* | |
2 | * $Id: SAXmyHtmlHandler.java 3373 2008-05-12 16:21:24Z xlv $ | |
3 | * | |
4 | * Copyright 2001, 2002 by Bruno Lowagie. | |
5 | * | |
6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
7 | * (the "License"); you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
9 | * | |
10 | * Software distributed under the License is distributed on an "AS IS" basis, | |
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 | * for the specific language governing rights and limitations under the License. | |
13 | * | |
14 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
15 | * | |
16 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
17 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
18 | * All Rights Reserved. | |
19 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
20 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
21 | * | |
22 | * Contributor(s): all the names of the contributors are added in the source code | |
23 | * where applicable. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
27 | * provisions of LGPL are applicable instead of those above. If you wish to | |
28 | * allow use of your version of this file only under the terms of the LGPL | |
29 | * License and not to allow others to use your version of this file under | |
30 | * the MPL, indicate your decision by deleting the provisions above and | |
31 | * replace them with the notice and other provisions required by the LGPL. | |
32 | * If you do not delete the provisions above, a recipient may use your version | |
33 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
34 | * | |
35 | * This library is free software; you can redistribute it and/or modify it | |
36 | * under the terms of the MPL as stated above or under the terms of the GNU | |
37 | * Library General Public License as published by the Free Software Foundation; | |
38 | * either version 2 of the License, or any later version. | |
39 | * | |
40 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
41 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
42 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
43 | * details. | |
44 | * | |
45 | * If you didn't download this code from the following link, you should check if | |
46 | * you aren't using an obsolete version: | |
47 | * http://www.lowagie.com/iText/ | |
48 | */ | |
49 | ||
50 | package com.lowagie.text.html; | |
51 | ||
52 | import java.util.HashMap; | |
53 | import java.util.Properties; | |
54 | ||
55 | import com.lowagie.text.ExceptionConverter; | |
56 | import org.xml.sax.Attributes; | |
57 | ||
58 | import com.lowagie.text.DocListener; | |
59 | import com.lowagie.text.DocumentException; | |
60 | import com.lowagie.text.Element; | |
61 | import com.lowagie.text.ElementTags; | |
62 | ||
63 | import com.lowagie.text.pdf.BaseFont; | |
64 | import com.lowagie.text.xml.SAXiTextHandler; | |
65 | import com.lowagie.text.xml.XmlPeer; | |
66 | ||
67 | /** | |
68 | * The <CODE>Tags</CODE>-class maps several XHTML-tags to iText-objects. | |
69 | */ | |
70 | ||
71 | public class SAXmyHtmlHandler extends SAXiTextHandler // SAXmyHandler | |
72 | { | |
73 | ||
74 | /** These are the properties of the body section. */ | |
75 | private Properties bodyAttributes = new Properties(); | |
76 | ||
77 | /** This is the status of the table border. */ | |
78 | private boolean tableBorder = false; | |
79 | ||
80 | /** | |
81 | * Constructs a new SAXiTextHandler that will translate all the events | |
82 | * triggered by the parser to actions on the <CODE>Document</CODE>-object. | |
83 | * | |
84 | * @param document | |
85 | * this is the document on which events must be triggered | |
86 | */ | |
87 | ||
88 | public SAXmyHtmlHandler(DocListener document) { | |
89 | super(document, new HtmlTagMap()); | |
90 | } | |
91 | /** | |
92 | * Constructs a new SAXiTextHandler that will translate all the events | |
93 | * triggered by the parser to actions on the <CODE>Document</CODE>-object. | |
94 | * | |
95 | * @param document | |
96 | * this is the document on which events must be triggered | |
97 | * @param bf | |
98 | */ | |
99 | ||
100 | public SAXmyHtmlHandler(DocListener document, BaseFont bf) { | |
101 | super(document, new HtmlTagMap(), bf); | |
102 | } | |
103 | ||
104 | /** | |
105 | * Constructs a new SAXiTextHandler that will translate all the events | |
106 | * triggered by the parser to actions on the <CODE>Document</CODE>-object. | |
107 | * | |
108 | * @param document | |
109 | * this is the document on which events must be triggered | |
110 | * @param htmlTags | |
111 | * a tagmap translating HTML tags to iText tags | |
112 | */ | |
113 | ||
114 | public SAXmyHtmlHandler(DocListener document, HashMap htmlTags) { | |
115 | super(document, htmlTags); | |
116 | } | |
117 | ||
118 | /** | |
119 | * This method gets called when a start tag is encountered. | |
120 | * | |
121 | * @param uri | |
122 | * the Uniform Resource Identifier | |
123 | * @param localName | |
124 | * the local name (without prefix), or the empty string if | |
125 | * Namespace processing is not being performed. | |
126 | * @param name | |
127 | * the name of the tag that is encountered | |
128 | * @param attrs | |
129 | * the list of attributes | |
130 | */ | |
131 | ||
132 | public void startElement(String uri, String localName, String name, | |
133 | Attributes attrs) { | |
134 | // System.err.println("Start: " + name); | |
135 | ||
136 | // super.handleStartingTags is replaced with handleStartingTags | |
137 | // suggestion by Vu Ngoc Tan/Hop | |
138 | name = name.toLowerCase(); | |
139 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isHtml(name)) { |
140 | // we do nothing | |
141 | return; | |
142 | } | |
143 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isHead(name)) { |
144 | // we do nothing | |
145 | return; | |
146 | } | |
147 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isTitle(name)) { |
148 | // we do nothing | |
149 | return; | |
150 | } | |
151 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isMeta(name)) { |
152 | // we look if we can change the body attributes | |
153 | String meta = null; | |
154 | String content = null; | |
155 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (attrs != null) { |
156 |
2
1. startElement : changed conditional boundary → NO_COVERAGE 2. startElement : negated conditional → NO_COVERAGE |
for (int i = 0; i < attrs.getLength(); i++) { |
157 | String attribute = attrs.getQName(i); | |
158 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (attribute.equalsIgnoreCase(HtmlTags.CONTENT)) |
159 | content = attrs.getValue(i); | |
160 |
1
1. startElement : negated conditional → NO_COVERAGE |
else if (attribute.equalsIgnoreCase(HtmlTags.NAME)) |
161 | meta = attrs.getValue(i); | |
162 | } | |
163 | } | |
164 |
2
1. startElement : negated conditional → NO_COVERAGE 2. startElement : negated conditional → NO_COVERAGE |
if (meta != null && content != null) { |
165 | bodyAttributes.put(meta, content); | |
166 | } | |
167 | return; | |
168 | } | |
169 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isLink(name)) { |
170 | // we do nothing for the moment, in a later version we could extract | |
171 | // the style sheet | |
172 | return; | |
173 | } | |
174 |
1
1. startElement : negated conditional → KILLED |
if (HtmlTagMap.isBody(name)) { |
175 | // maybe we could extract some info about the document: color, | |
176 | // margins,... | |
177 | // but that's for a later version... | |
178 | XmlPeer peer = new XmlPeer(ElementTags.ITEXT, name); | |
179 |
1
1. startElement : removed call to com/lowagie/text/xml/XmlPeer::addAlias → NO_COVERAGE |
peer.addAlias(ElementTags.TOP, HtmlTags.TOPMARGIN); |
180 |
1
1. startElement : removed call to com/lowagie/text/xml/XmlPeer::addAlias → NO_COVERAGE |
peer.addAlias(ElementTags.BOTTOM, HtmlTags.BOTTOMMARGIN); |
181 |
1
1. startElement : removed call to com/lowagie/text/xml/XmlPeer::addAlias → NO_COVERAGE |
peer.addAlias(ElementTags.RIGHT, HtmlTags.RIGHTMARGIN); |
182 |
1
1. startElement : removed call to com/lowagie/text/xml/XmlPeer::addAlias → NO_COVERAGE |
peer.addAlias(ElementTags.LEFT, HtmlTags.LEFTMARGIN); |
183 |
1
1. startElement : removed call to java/util/Properties::putAll → NO_COVERAGE |
bodyAttributes.putAll(peer.getAttributes(attrs)); |
184 |
1
1. startElement : removed call to com/lowagie/text/html/SAXmyHtmlHandler::handleStartingTags → NO_COVERAGE |
handleStartingTags(peer.getTag(), bodyAttributes); |
185 | return; | |
186 | } | |
187 |
1
1. startElement : negated conditional → KILLED |
if (myTags.containsKey(name)) { |
188 | XmlPeer peer = (XmlPeer) myTags.get(name); | |
189 |
2
1. startElement : negated conditional → SURVIVED 2. startElement : negated conditional → SURVIVED |
if (ElementTags.TABLE.equals(peer.getTag()) || ElementTags.CELL.equals(peer.getTag())) { |
190 | Properties p = peer.getAttributes(attrs); | |
191 | String value; | |
192 |
1
1. startElement : negated conditional → SURVIVED |
if (ElementTags.TABLE.equals(peer.getTag()) |
193 |
1
1. startElement : negated conditional → KILLED |
&& (value = p.getProperty(ElementTags.BORDERWIDTH)) != null) { |
194 |
2
1. startElement : changed conditional boundary → NO_COVERAGE 2. startElement : negated conditional → NO_COVERAGE |
if (Float.parseFloat(value + "f") > 0) { |
195 | tableBorder = true; | |
196 | } | |
197 | } | |
198 |
1
1. startElement : negated conditional → SURVIVED |
if (tableBorder) { |
199 | p.put(ElementTags.LEFT, String.valueOf(true)); | |
200 | p.put(ElementTags.RIGHT, String.valueOf(true)); | |
201 | p.put(ElementTags.TOP, String.valueOf(true)); | |
202 | p.put(ElementTags.BOTTOM, String.valueOf(true)); | |
203 | } | |
204 |
1
1. startElement : removed call to com/lowagie/text/html/SAXmyHtmlHandler::handleStartingTags → KILLED |
handleStartingTags(peer.getTag(), p); |
205 | return; | |
206 | } | |
207 |
1
1. startElement : removed call to com/lowagie/text/html/SAXmyHtmlHandler::handleStartingTags → SURVIVED |
handleStartingTags(peer.getTag(), peer.getAttributes(attrs)); |
208 | return; | |
209 | } | |
210 | Properties attributes = new Properties(); | |
211 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (attrs != null) { |
212 |
2
1. startElement : changed conditional boundary → NO_COVERAGE 2. startElement : negated conditional → NO_COVERAGE |
for (int i = 0; i < attrs.getLength(); i++) { |
213 | String attribute = attrs.getQName(i).toLowerCase(); | |
214 | attributes.setProperty(attribute, attrs.getValue(i).toLowerCase()); | |
215 | } | |
216 | } | |
217 |
1
1. startElement : removed call to com/lowagie/text/html/SAXmyHtmlHandler::handleStartingTags → NO_COVERAGE |
handleStartingTags(name, attributes); |
218 | } | |
219 | ||
220 | /** | |
221 | * This method gets called when an end tag is encountered. | |
222 | * | |
223 | * @param uri | |
224 | * the Uniform Resource Identifier | |
225 | * @param lname | |
226 | * the local name (without prefix), or the empty string if | |
227 | * Namespace processing is not being performed. | |
228 | * @param name | |
229 | * the name of the tag that ends | |
230 | */ | |
231 | ||
232 | public void endElement(String uri, String lname, String name) { | |
233 | // System.err.println("End: " + name); | |
234 | name = name.toLowerCase(); | |
235 |
1
1. endElement : negated conditional → KILLED |
if (ElementTags.PARAGRAPH.equals(name)) { |
236 | try { | |
237 | document.add((Element) stack.pop()); | |
238 | return; | |
239 | } catch (DocumentException e) { | |
240 | throw new ExceptionConverter(e); | |
241 | } | |
242 | } | |
243 |
1
1. endElement : negated conditional → SURVIVED |
if (HtmlTagMap.isHead(name)) { |
244 | // we do nothing | |
245 | return; | |
246 | } | |
247 |
1
1. endElement : negated conditional → SURVIVED |
if (HtmlTagMap.isTitle(name)) { |
248 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (currentChunk != null) { |
249 | bodyAttributes.put(ElementTags.TITLE, currentChunk.getContent()); | |
250 | } | |
251 | return; | |
252 | } | |
253 |
1
1. endElement : negated conditional → SURVIVED |
if (HtmlTagMap.isMeta(name)) { |
254 | // we do nothing | |
255 | return; | |
256 | } | |
257 |
1
1. endElement : negated conditional → SURVIVED |
if (HtmlTagMap.isLink(name)) { |
258 | // we do nothing | |
259 | return; | |
260 | } | |
261 |
1
1. endElement : negated conditional → SURVIVED |
if (HtmlTagMap.isBody(name)) { |
262 | // we do nothing | |
263 | return; | |
264 | } | |
265 |
1
1. endElement : negated conditional → KILLED |
if (myTags.containsKey(name)) { |
266 | XmlPeer peer = (XmlPeer) myTags.get(name); | |
267 |
1
1. endElement : negated conditional → SURVIVED |
if (ElementTags.TABLE.equals(peer.getTag())) { |
268 | tableBorder = false; | |
269 | } | |
270 |
1
1. endElement : removed call to com/lowagie/text/xml/SAXiTextHandler::handleEndingTags → SURVIVED |
super.handleEndingTags(peer.getTag()); |
271 | return; | |
272 | } | |
273 | // super.handleEndingTags is replaced with handleEndingTags | |
274 | // suggestion by Ken Auer | |
275 |
1
1. endElement : removed call to com/lowagie/text/html/SAXmyHtmlHandler::handleEndingTags → NO_COVERAGE |
handleEndingTags(name); |
276 | } | |
277 | } | |
Mutations | ||
139 |
1.1 |
|
143 |
1.1 |
|
147 |
1.1 |
|
151 |
1.1 |
|
155 |
1.1 |
|
156 |
1.1 2.2 |
|
158 |
1.1 |
|
160 |
1.1 |
|
164 |
1.1 2.2 |
|
169 |
1.1 |
|
174 |
1.1 |
|
179 |
1.1 |
|
180 |
1.1 |
|
181 |
1.1 |
|
182 |
1.1 |
|
183 |
1.1 |
|
184 |
1.1 |
|
187 |
1.1 |
|
189 |
1.1 2.2 |
|
192 |
1.1 |
|
193 |
1.1 |
|
194 |
1.1 2.2 |
|
198 |
1.1 |
|
204 |
1.1 |
|
207 |
1.1 |
|
211 |
1.1 |
|
212 |
1.1 2.2 |
|
217 |
1.1 |
|
235 |
1.1 |
|
243 |
1.1 |
|
247 |
1.1 |
|
248 |
1.1 |
|
253 |
1.1 |
|
257 |
1.1 |
|
261 |
1.1 |
|
265 |
1.1 |
|
267 |
1.1 |
|
270 |
1.1 |
|
275 |
1.1 |