1 /*
2 * $Id: TempXMLManager.java 2993 2011-11-24 19:51:48Z andrewinkler $
3 * ============================================================================
4 * Project gluehloch-homepage-core
5 * Copyright (c) 2004-2010 by Andre Winkler. All rights reserved.
6 * ============================================================================
7 * GNU LESSER GENERAL PUBLIC LICENSE
8 * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26 package de.awtools.homegen.xml;
27
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.UnsupportedEncodingException;
32 import java.util.ArrayList;
33 import java.util.Iterator;
34 import java.util.List;
35
36 import org.apache.commons.io.IOUtils;
37 import org.apache.commons.lang.StringUtils;
38 import org.dom4j.Document;
39 import org.dom4j.DocumentException;
40 import org.dom4j.Node;
41 import org.dom4j.io.OutputFormat;
42 import org.dom4j.io.SAXReader;
43 import org.dom4j.io.XMLWriter;
44
45 import de.awtools.homegen.TransformerException;
46 import de.awtools.xml.XMLUtils;
47
48 /**
49 * Verwaltet die XML/HTML Schnipsel die nach dem ersten Transformationsprozeß
50 * entstanden sind. Die XML/HTML Schnipsel besitzen folgende Struktur:
51 * <pre>
52 * document/head -> Strukturinformationen: CSS.
53 * document/body -> Enthält HTML-Code. Wird 1:1 übernommen.
54 * </pre>
55 *
56 * @version $LastChangedRevision: 2993 $ $LastChangedDate: 2011-11-24 20:51:48 +0100 (Thu, 24 Nov 2011) $
57 * @author by Andre Winkler, $LastChangedBy: andrewinkler $
58 */
59 public final class TempXMLManager {
60
61 /** Zeichensatzcodierung. */
62 private final String encoding;
63
64 /** Der 'body' des XML/HTML Schnipsels. */
65 private String body;
66
67 /** Der 'title' für die HTML Seite. */
68 private String title;
69
70 /** Die einzubindenden CSS Dateien. */
71 private List<String> cssImports;
72
73 /**
74 * Konstruktor.
75 *
76 * @param _encoding Zeichensatzkodierung (z.B. UTF-8).
77 */
78 public TempXMLManager(final String _encoding) {
79 encoding = _encoding;
80 }
81
82 /**
83 * Liefert den 'body' des XML/HTML Schnipsels. Der Inhalt des body Tags
84 * ohne das 'body' Tag selbst.
85 *
86 * @return Der 'body'.
87 */
88 public String getBody() {
89 return body;
90 }
91
92 /**
93 * Liefert den 'title' für die HTML Seite.
94 *
95 * @return Der 'title'.
96 */
97 public String getTitle() {
98 return title;
99 }
100
101 /**
102 * Die lokal zu ergänzenden CSS Dateien.
103 *
104 * @return Ein Liste mit CSS Import Anweisungen.
105 */
106 public List<String> getCss() {
107 return cssImports;
108 }
109
110 /**
111 * Parst einen XML/HTML Schnipsel und stellt dessen Inhalt zur Verfügung.
112 *
113 * @param in Ein InputStream für einen XML/HTML Schnipsel.
114 * @param name Der Name des InputStreams. I.d.R. der Dateiname oder eine
115 * andere ID, die den InputStream im Fehlerfall identifizieren kann.
116 */
117 public void parse(final InputStream in, final String name) {
118 SAXReader reader = new SAXReader();
119 reader.setStripWhitespaceText(false);
120 try {
121 Document document = reader.read(in);
122 title = extractTitle(document);
123 body = extractBody(document);
124 cssImports = extractCss(document);
125 } catch (DocumentException ex) {
126 throw new TransformerException(name, ex);
127 }
128 }
129
130 /**
131 * Extrahiert den Titel für die HTML Seite.
132 *
133 * @param document Ein XML Dokument.
134 * @return Der Titel für die HTML Seite.
135 */
136 private String extractTitle(final Document document) {
137 Node node = document.selectSingleNode("//document/head/title");
138 String result = null;
139 if ((node != null) && (!StringUtils.isBlank(node.getText()))) {
140 result = node.getText();
141 }
142 return result;
143 }
144
145 /**
146 * Extrahiert die CSS Import Informationen.
147 *
148 * @param document Ein XML Dokument.
149 * @return Die CSS Import Anweisungen.
150 */
151 private List<String> extractCss(final Document document) {
152 List<?> nodes = document.selectNodes("//document/head/css");
153 List<String> css = new ArrayList<String>(nodes.size());
154 for (Iterator<?> i = nodes.iterator(); i.hasNext();) {
155 Node node = (Node) i.next();
156 css.add(node.getText());
157 }
158 return css;
159 }
160
161 /**
162 * Extrahiert den Body und liefert diesen als String zurück ohne das
163 * 'body' Tag selbst.
164 *
165 * @param document Ein XML Dokument.
166 * @return Der Body.
167 */
168 private String extractBody(final Document document) {
169 Node node = document.selectSingleNode("//document/body/.");
170 String result = null;
171
172 // Möglicherweise ist der Dokumenten-Body leer. Dann die nächsten
173 // Schritte überspringen.
174 if (node != null) {
175 OutputFormat format = OutputFormat.createPrettyPrint();
176 format.setEncoding(encoding);
177 format.setNewlines(true);
178 format.setLineSeparator("\n");
179 format.setTrimText(false);
180
181 ByteArrayOutputStream baos = new ByteArrayOutputStream();
182 XMLWriter writer = null;
183 try {
184 writer = new XMLWriter(baos, format);
185 writer.write(node);
186 } catch (UnsupportedEncodingException ex) {
187 throw new TransformerException(ex);
188 } catch (IOException ex) {
189 throw new TransformerException(ex);
190 } finally {
191 IOUtils.closeQuietly(baos);
192 XMLUtils.close(writer);
193 }
194
195 result = StringUtils.replaceOnce(baos.toString(), "<body>", " ");
196 result = StringUtils.replaceOnce(result, "</body>", " ");
197 // @todo Problem:
198 // javascript:menuManager.openHref('./subitem3.html'); wird nach
199 // javascript:menuManager.openHref('./subitem3.html')
200 // umgewandelt!
201 result = StringUtils.replace(result, "'", "'");
202 }
203
204 return result;
205 }
206
207 }