1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.internal;
17
18 import static org.mybatis.generator.internal.util.messages.Messages.getString;
19
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22
23 import org.mybatis.generator.exception.ShellException;
24 import org.w3c.dom.Attr;
25 import org.w3c.dom.CDATASection;
26 import org.w3c.dom.Comment;
27 import org.w3c.dom.Document;
28 import org.w3c.dom.DocumentType;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.EntityReference;
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.ProcessingInstruction;
34 import org.w3c.dom.Text;
35
36
37
38
39
40
41
42
43
44 public class DomWriter {
45
46
47 protected PrintWriter printWriter;
48
49
50 protected boolean isXML11;
51
52
53
54
55 public DomWriter() {
56 super();
57 }
58
59
60
61
62
63
64
65
66
67
68 public synchronized String toString(Document document)
69 throws ShellException {
70 StringWriter sw = new StringWriter();
71 printWriter = new PrintWriter(sw);
72 write(document);
73 String s = sw.toString();
74 return s;
75 }
76
77
78
79
80
81
82
83
84 protected Attr[] sortAttributes(NamedNodeMap attrs) {
85
86 int len = (attrs != null) ? attrs.getLength() : 0;
87 Attr array[] = new Attr[len];
88 for (int i = 0; i < len; i++) {
89 array[i] = (Attr) attrs.item(i);
90 }
91 for (int i = 0; i < len - 1; i++) {
92 String name = array[i].getNodeName();
93 int index = i;
94 for (int j = i + 1; j < len; j++) {
95 String curName = array[j].getNodeName();
96 if (curName.compareTo(name) < 0) {
97 name = curName;
98 index = j;
99 }
100 }
101 if (index != i) {
102 Attr temp = array[i];
103 array[i] = array[index];
104 array[index] = temp;
105 }
106 }
107
108 return array;
109
110 }
111
112
113
114
115
116
117
118
119
120 protected void normalizeAndPrint(String s, boolean isAttValue) {
121
122 int len = (s != null) ? s.length() : 0;
123 for (int i = 0; i < len; i++) {
124 char c = s.charAt(i);
125 normalizeAndPrint(c, isAttValue);
126 }
127 }
128
129
130
131
132
133
134
135
136
137 protected void normalizeAndPrint(char c, boolean isAttValue) {
138
139 switch (c) {
140 case '<': {
141 printWriter.print("<");
142 break;
143 }
144 case '>': {
145 printWriter.print(">");
146 break;
147 }
148 case '&': {
149 printWriter.print("&");
150 break;
151 }
152 case '"': {
153
154
155 if (isAttValue) {
156 printWriter.print(""");
157 } else {
158 printWriter.print('"');
159 }
160 break;
161 }
162 case '\r': {
163
164
165
166
167 printWriter.print("
");
168 break;
169 }
170 case '\n': {
171
172
173
174
175
176 printWriter.print(System.getProperty("line.separator"));
177 break;
178 }
179 default: {
180
181
182
183
184
185
186
187
188
189
190 if (isXML11
191 && ((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A)
192 || (c >= 0x7F && c <= 0x9F) || c == 0x2028)
193 || isAttValue && (c == 0x09 || c == 0x0A)) {
194 printWriter.print("&#x");
195 printWriter.print(Integer.toHexString(c).toUpperCase());
196 printWriter.print(';');
197 } else {
198 printWriter.print(c);
199 }
200 }
201 }
202 }
203
204
205
206
207
208
209
210
211 protected String getVersion(Document document) {
212 if (document == null) {
213 return null;
214 }
215
216 return document.getXmlVersion();
217 }
218
219
220
221
222
223
224
225
226
227 protected void writeAnyNode(Node node) throws ShellException {
228
229 if (node == null) {
230 return;
231 }
232
233 short type = node.getNodeType();
234 switch (type) {
235 case Node.DOCUMENT_NODE:
236 write((Document) node);
237 break;
238
239 case Node.DOCUMENT_TYPE_NODE:
240 write((DocumentType) node);
241 break;
242
243 case Node.ELEMENT_NODE:
244 write((Element) node);
245 break;
246
247 case Node.ENTITY_REFERENCE_NODE:
248 write((EntityReference) node);
249 break;
250
251 case Node.CDATA_SECTION_NODE:
252 write((CDATASection) node);
253 break;
254
255 case Node.TEXT_NODE:
256 write((Text) node);
257 break;
258
259 case Node.PROCESSING_INSTRUCTION_NODE:
260 write((ProcessingInstruction) node);
261 break;
262
263 case Node.COMMENT_NODE:
264 write((Comment) node);
265 break;
266
267 default:
268 throw new ShellException(getString(
269 "RuntimeError.18", Short.toString(type)));
270 }
271 }
272
273
274
275
276
277
278
279
280
281 protected void write(Document node) throws ShellException {
282 isXML11 = "1.1".equals(getVersion(node));
283 if (isXML11) {
284 printWriter.println("<?xml version=\"1.1\" encoding=\"UTF-8\"?>");
285 } else {
286 printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
287 }
288 printWriter.flush();
289 write(node.getDoctype());
290 write(node.getDocumentElement());
291 }
292
293
294
295
296
297
298
299
300
301 protected void write(DocumentType node) throws ShellException {
302 printWriter.print("<!DOCTYPE ");
303 printWriter.print(node.getName());
304 String publicId = node.getPublicId();
305 String systemId = node.getSystemId();
306 if (publicId != null) {
307 printWriter.print(" PUBLIC \"");
308 printWriter.print(publicId);
309 printWriter.print("\" \"");
310 printWriter.print(systemId);
311 printWriter.print('\"');
312 } else if (systemId != null) {
313 printWriter.print(" SYSTEM \"");
314 printWriter.print(systemId);
315 printWriter.print('"');
316 }
317
318 String internalSubset = node.getInternalSubset();
319 if (internalSubset != null) {
320 printWriter.println(" [");
321 printWriter.print(internalSubset);
322 printWriter.print(']');
323 }
324 printWriter.println('>');
325 }
326
327
328
329
330
331
332
333
334
335 protected void write(Element node) throws ShellException {
336 printWriter.print('<');
337 printWriter.print(node.getNodeName());
338 Attr attrs[] = sortAttributes(node.getAttributes());
339 for (Attr attr : attrs) {
340 printWriter.print(' ');
341 printWriter.print(attr.getNodeName());
342 printWriter.print("=\"");
343 normalizeAndPrint(attr.getNodeValue(), true);
344 printWriter.print('"');
345 }
346
347 if (node.getChildNodes().getLength() == 0) {
348 printWriter.print(" />");
349 printWriter.flush();
350 } else {
351 printWriter.print('>');
352 printWriter.flush();
353
354 Node child = node.getFirstChild();
355 while (child != null) {
356 writeAnyNode(child);
357 child = child.getNextSibling();
358 }
359
360 printWriter.print("</");
361 printWriter.print(node.getNodeName());
362 printWriter.print('>');
363 printWriter.flush();
364 }
365 }
366
367
368
369
370
371
372
373 protected void write(EntityReference node) {
374 printWriter.print('&');
375 printWriter.print(node.getNodeName());
376 printWriter.print(';');
377 printWriter.flush();
378 }
379
380
381
382
383
384
385
386 protected void write(CDATASection node) {
387 printWriter.print("<![CDATA[");
388 String data = node.getNodeValue();
389
390
391
392 int len = (data != null) ? data.length() : 0;
393 for (int i = 0; i < len; i++) {
394 char c = data.charAt(i);
395 if (c == '\n') {
396 printWriter.print(System.getProperty("line.separator"));
397 } else {
398 printWriter.print(c);
399 }
400 }
401 printWriter.print("]]>");
402 printWriter.flush();
403 }
404
405
406
407
408
409
410
411 protected void write(Text node) {
412 normalizeAndPrint(node.getNodeValue(), false);
413 printWriter.flush();
414 }
415
416
417
418
419
420
421
422 protected void write(ProcessingInstruction node) {
423 printWriter.print("<?");
424 printWriter.print(node.getNodeName());
425 String data = node.getNodeValue();
426 if (data != null && data.length() > 0) {
427 printWriter.print(' ');
428 printWriter.print(data);
429 }
430 printWriter.print("?>");
431 printWriter.flush();
432 }
433
434
435
436
437
438
439
440 protected void write(Comment node) {
441 printWriter.print("<!--");
442 String comment = node.getNodeValue();
443 if (comment != null && comment.length() > 0) {
444 normalizeAndPrint(comment, false);
445 }
446 printWriter.print("-->");
447 printWriter.flush();
448 }
449 }