root / branches / v2_0_0_prep / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / rendering / legend / XmlBuilder.java @ 21200
History | View | Annotate | Download (12.4 KB)
1 |
package org.gvsig.fmap.mapcontext.rendering.legend; |
---|---|
2 |
|
3 |
import java.util.HashMap; |
4 |
import java.util.Stack; |
5 |
|
6 |
/**
|
7 |
* Title: XmlBuilder
|
8 |
* Description: Util class to build xml
|
9 |
* @author laura
|
10 |
*/
|
11 |
public class XmlBuilder |
12 |
{ |
13 |
// Default size of the XML document to be generated. Used to set the initial
|
14 |
// capacity of m_xml.
|
15 |
private static final int DEF_XMLDOC_SIZE = 256; |
16 |
|
17 |
// Pad unit.
|
18 |
private static final String PAD = " "; |
19 |
|
20 |
|
21 |
// Number of pre-defined pad strings, one for each pad
|
22 |
// level (0..NUM_PADSTRINGS-1). Should at least be set to 10 for performance.
|
23 |
private static final int NUM_PADSTRINGS = 20; |
24 |
|
25 |
// Byte representation of '\n'.
|
26 |
private static final byte[] NEWLINE_BYTES = "\n".getBytes(); |
27 |
|
28 |
|
29 |
// Array of pad strings, each preceded by a '\n' character.
|
30 |
private static String s_padStrings[]; |
31 |
|
32 |
// XML-encoded newline character.
|
33 |
private static String s_newlineXmlEnc; |
34 |
|
35 |
|
36 |
// XML document being built.
|
37 |
private StringBuffer m_xml = new StringBuffer(DEF_XMLDOC_SIZE); |
38 |
|
39 |
// Scratch buffer exclusively used to encode strings.
|
40 |
private StringBuffer m_encodeBuf = new StringBuffer(40); |
41 |
|
42 |
// Current pad string.
|
43 |
private String m_pad = ""; |
44 |
|
45 |
// If set, indentation will be added to the XML document.
|
46 |
private boolean m_autoPad; |
47 |
|
48 |
// Stack of strings. The string at the top is the tag name of the current
|
49 |
// XML block. The string immediately below the top is the tag name of the
|
50 |
// XML block that immediately encloses the current XML block.
|
51 |
protected Stack m_openElements = new Stack(); |
52 |
|
53 |
// Current pad level (0, 1, 2, ...).
|
54 |
private int m_padLevel = 0; |
55 |
|
56 |
private String encoding = "UTF-8"; |
57 |
|
58 |
/*
|
59 |
* Create the pad strings.
|
60 |
*/
|
61 |
static
|
62 |
{ |
63 |
s_padStrings = new String[NUM_PADSTRINGS]; |
64 |
String pad = ""; |
65 |
|
66 |
for (int i = 0; i < NUM_PADSTRINGS; i++) |
67 |
{ |
68 |
s_padStrings[i] = "\n" + pad;
|
69 |
pad += PAD; |
70 |
} |
71 |
|
72 |
StringBuffer tmp = new StringBuffer(); |
73 |
|
74 |
for (int i = 0; i < NEWLINE_BYTES.length; i++) |
75 |
{ |
76 |
tmp.append("&#");
|
77 |
tmp.append(NEWLINE_BYTES[i]); |
78 |
tmp.append(";");
|
79 |
} |
80 |
|
81 |
s_newlineXmlEnc = tmp.toString(); |
82 |
} |
83 |
|
84 |
|
85 |
/**
|
86 |
* Constructor. The XML document to be generated will automatically be
|
87 |
* indented.
|
88 |
*/
|
89 |
public XmlBuilder()
|
90 |
{ |
91 |
this(true); |
92 |
} |
93 |
|
94 |
/**
|
95 |
* Constructor.
|
96 |
*
|
97 |
* @param autoPad if set, the XML document to be generated will
|
98 |
* automatically be indented.
|
99 |
*/
|
100 |
public XmlBuilder(boolean autoPad) |
101 |
{ |
102 |
m_autoPad = autoPad; |
103 |
m_padLevel = 0;
|
104 |
m_pad = s_padStrings[m_padLevel]; |
105 |
} |
106 |
|
107 |
/**
|
108 |
* Reset this XmlBuilder.
|
109 |
*/
|
110 |
public void reset() |
111 |
{ |
112 |
m_padLevel = 0;
|
113 |
m_pad = s_padStrings[m_padLevel]; |
114 |
m_xml.setLength(0);
|
115 |
} |
116 |
|
117 |
/**
|
118 |
* Adds raw data to the xml.
|
119 |
*/
|
120 |
public void writeRaw(String raw) |
121 |
{ |
122 |
m_xml.append(raw); |
123 |
} |
124 |
|
125 |
/**
|
126 |
* Adds a comment to the xml.
|
127 |
*/
|
128 |
public void writeComment(String comment) |
129 |
{ |
130 |
if (m_autoPad)
|
131 |
{ |
132 |
m_xml.append(m_pad); |
133 |
} |
134 |
|
135 |
m_xml.append("<!-- ");
|
136 |
encode(comment, m_xml); |
137 |
m_xml.append(" -->\n");
|
138 |
} |
139 |
|
140 |
/**
|
141 |
* Writes the XML document header.
|
142 |
*/
|
143 |
public void writeHeader() |
144 |
{ |
145 |
// XML document header.
|
146 |
final String HEADER = "<?xml version=\"1.0\" encoding=\""+encoding+"\"?>\n"; |
147 |
|
148 |
m_xml.append(HEADER); |
149 |
} |
150 |
|
151 |
/**
|
152 |
* Sets the encoding used in the XML. By default UTF-8 is used.
|
153 |
* @param encoding
|
154 |
*/
|
155 |
public void setEncoding(String encoding) { |
156 |
this.encoding = encoding;
|
157 |
} |
158 |
|
159 |
/**
|
160 |
* Adds a opening and closing tag with charcter data.
|
161 |
*/
|
162 |
public void writeTag(String name, String data) |
163 |
{ |
164 |
name = encode(name); |
165 |
|
166 |
if (m_autoPad)
|
167 |
{ |
168 |
m_xml.append(m_pad); |
169 |
} |
170 |
|
171 |
m_xml.append("<");
|
172 |
m_xml.append(name); |
173 |
m_xml.append(">");
|
174 |
encode(data, m_xml); |
175 |
m_xml.append("</");
|
176 |
m_xml.append(name); |
177 |
m_xml.append(">");
|
178 |
} |
179 |
|
180 |
/**
|
181 |
* Adds a opening and closing tag with attributes.
|
182 |
*/
|
183 |
public void writeTag(String name, HashMap attributes) |
184 |
{ |
185 |
if (m_autoPad)
|
186 |
{ |
187 |
m_xml.append(m_pad); |
188 |
} |
189 |
|
190 |
m_xml.append("<");
|
191 |
encode(name, m_xml); |
192 |
m_xml.append(" ");
|
193 |
|
194 |
Object elems[] = attributes.keySet().toArray(); |
195 |
|
196 |
for (int i = 0; i < elems.length; i++) |
197 |
{ |
198 |
String nm = (String)elems[i]; |
199 |
String val = (String)attributes.get(nm); |
200 |
|
201 |
encode(nm, m_xml); |
202 |
m_xml.append("=\"");
|
203 |
encode(val, m_xml); |
204 |
m_xml.append("\" ");
|
205 |
} |
206 |
|
207 |
m_xml.append("/>");
|
208 |
} |
209 |
|
210 |
/**
|
211 |
* Adds a opening and closing tag with an attribute and character data.
|
212 |
*/
|
213 |
public void writeTag(String name, String attr1Name, String attr1Value |
214 |
, String attr2Name, String attr2Value) |
215 |
{ |
216 |
if (m_autoPad)
|
217 |
{ |
218 |
m_xml.append(m_pad); |
219 |
} |
220 |
|
221 |
m_xml.append("<");
|
222 |
encode(name, m_xml); |
223 |
m_xml.append(" ");
|
224 |
|
225 |
encode(attr1Name, m_xml); |
226 |
m_xml.append("=\"");
|
227 |
encode(attr1Value, m_xml); |
228 |
m_xml.append("\" ");
|
229 |
|
230 |
encode(attr2Name, m_xml); |
231 |
m_xml.append("=\"");
|
232 |
encode(attr2Value, m_xml); |
233 |
m_xml.append("\" ");
|
234 |
|
235 |
m_xml.append("/>");
|
236 |
} |
237 |
|
238 |
/**
|
239 |
* Adds a opening and closing tag with an attribute and character data.
|
240 |
*/
|
241 |
public void writeTag(String name, String data, String attrName, String attrValue) |
242 |
{ |
243 |
name = encode(name); |
244 |
|
245 |
if (m_autoPad)
|
246 |
{ |
247 |
m_xml.append(m_pad); |
248 |
} |
249 |
|
250 |
m_xml.append("<");
|
251 |
m_xml.append(name); |
252 |
m_xml.append(" ");
|
253 |
|
254 |
encode(attrName, m_xml); |
255 |
m_xml.append("=\"");
|
256 |
encode(attrValue, m_xml); |
257 |
m_xml.append("\" ");
|
258 |
|
259 |
m_xml.append(">");
|
260 |
encode(data, m_xml); |
261 |
m_xml.append("</");
|
262 |
m_xml.append(name); |
263 |
m_xml.append(">");
|
264 |
} |
265 |
|
266 |
/**
|
267 |
* Adds a opening and closing tag with two attributes and character data.
|
268 |
*/
|
269 |
public void writeTag(String name, String data, String attr1Name, String attr1Value |
270 |
, String attr2Name, String attr2Value) |
271 |
{ |
272 |
name = encode(name); |
273 |
|
274 |
if (m_autoPad)
|
275 |
{ |
276 |
m_xml.append(m_pad); |
277 |
} |
278 |
|
279 |
m_xml.append("<");
|
280 |
m_xml.append(name); |
281 |
m_xml.append(" ");
|
282 |
|
283 |
encode(attr1Name, m_xml); |
284 |
m_xml.append("=\"");
|
285 |
encode(attr1Value, m_xml); |
286 |
m_xml.append("\" ");
|
287 |
|
288 |
encode(attr2Name, m_xml); |
289 |
m_xml.append("=\"");
|
290 |
encode(attr2Value, m_xml); |
291 |
m_xml.append("\" ");
|
292 |
|
293 |
m_xml.append(">");
|
294 |
encode(data, m_xml); |
295 |
m_xml.append("</");
|
296 |
m_xml.append(name); |
297 |
m_xml.append(">");
|
298 |
} |
299 |
|
300 |
/**
|
301 |
* Adds a opening and closing tag with attributes and character data.
|
302 |
*/
|
303 |
public void writeTag(String name, String data, HashMap attributes) |
304 |
{ |
305 |
name = encode(name); |
306 |
|
307 |
if (m_autoPad)
|
308 |
{ |
309 |
m_xml.append(m_pad); |
310 |
} |
311 |
|
312 |
m_xml.append("<");
|
313 |
m_xml.append(name); |
314 |
m_xml.append(" ");
|
315 |
|
316 |
Object elems[] = attributes.keySet().toArray(); |
317 |
|
318 |
for (int i = 0; i < elems.length; i++) |
319 |
{ |
320 |
String nm = (String)elems[i]; |
321 |
String val = (String)attributes.get(nm); |
322 |
|
323 |
encode(nm, m_xml); |
324 |
m_xml.append("=\"");
|
325 |
encode(val, m_xml); |
326 |
m_xml.append("\" ");
|
327 |
} |
328 |
|
329 |
m_xml.append(">");
|
330 |
encode(data, m_xml); |
331 |
m_xml.append("</");
|
332 |
m_xml.append(name); |
333 |
m_xml.append(">");
|
334 |
} |
335 |
|
336 |
/**
|
337 |
* Writes an opening tag
|
338 |
*/
|
339 |
public void openTag(String name) |
340 |
{ |
341 |
name = encode(name); |
342 |
|
343 |
m_openElements.push(name); // must be encoded!
|
344 |
|
345 |
if (m_autoPad)
|
346 |
{ |
347 |
m_xml.append(m_pad); |
348 |
} |
349 |
|
350 |
m_xml.append("<");
|
351 |
m_xml.append(name); |
352 |
m_xml.append(">");
|
353 |
|
354 |
if (m_autoPad)
|
355 |
{ |
356 |
m_padLevel++; |
357 |
|
358 |
if (m_padLevel < NUM_PADSTRINGS)
|
359 |
{ |
360 |
m_pad = s_padStrings[m_padLevel]; |
361 |
} |
362 |
else // really deep nesting level |
363 |
{ |
364 |
m_pad += PAD; |
365 |
} |
366 |
} |
367 |
} |
368 |
|
369 |
/**
|
370 |
* Writes an opening tag with one attribute.
|
371 |
*/
|
372 |
public void openTag(String name, String attrName, String attrValue) |
373 |
{ |
374 |
name = encode(name); |
375 |
|
376 |
m_openElements.push(name); // must be encoded!
|
377 |
|
378 |
if (m_autoPad)
|
379 |
{ |
380 |
m_xml.append(m_pad); |
381 |
} |
382 |
|
383 |
m_xml.append("<");
|
384 |
m_xml.append(name); |
385 |
m_xml.append(" ");
|
386 |
|
387 |
encode(attrName, m_xml); |
388 |
m_xml.append("=\"");
|
389 |
encode(attrValue, m_xml); |
390 |
m_xml.append("\" ");
|
391 |
|
392 |
m_xml.append(">");
|
393 |
|
394 |
if (m_autoPad)
|
395 |
{ |
396 |
m_padLevel++; |
397 |
|
398 |
if (m_padLevel < NUM_PADSTRINGS)
|
399 |
{ |
400 |
m_pad = s_padStrings[m_padLevel]; |
401 |
} |
402 |
else // really deep nesting level |
403 |
{ |
404 |
m_pad += PAD; |
405 |
} |
406 |
} |
407 |
} |
408 |
|
409 |
/**
|
410 |
* Writes an opening tag with two attributes.
|
411 |
*/
|
412 |
public void openTag(String name, String attr1Name, String attr1Value |
413 |
, String attr2Name, String attr2Value) |
414 |
{ |
415 |
name = encode(name); |
416 |
|
417 |
m_openElements.push(name); // must be encoded!
|
418 |
|
419 |
if (m_autoPad)
|
420 |
{ |
421 |
m_xml.append(m_pad); |
422 |
} |
423 |
|
424 |
m_xml.append("<");
|
425 |
m_xml.append(name); |
426 |
m_xml.append(" ");
|
427 |
|
428 |
encode(attr1Name, m_xml); |
429 |
m_xml.append("=\"");
|
430 |
encode(attr1Value, m_xml); |
431 |
m_xml.append("\" ");
|
432 |
|
433 |
encode(attr2Name, m_xml); |
434 |
m_xml.append("=\"");
|
435 |
encode(attr2Value, m_xml); |
436 |
m_xml.append("\" ");
|
437 |
|
438 |
m_xml.append(">");
|
439 |
|
440 |
if (m_autoPad)
|
441 |
{ |
442 |
m_padLevel++; |
443 |
|
444 |
if (m_padLevel < NUM_PADSTRINGS)
|
445 |
{ |
446 |
m_pad = s_padStrings[m_padLevel]; |
447 |
} |
448 |
else // really deep nesting level |
449 |
{ |
450 |
m_pad += PAD; |
451 |
} |
452 |
} |
453 |
} |
454 |
|
455 |
/**
|
456 |
* Writes an opening tag with attributes.
|
457 |
*/
|
458 |
public void openTag(String name, HashMap attributes) |
459 |
{ |
460 |
name = encode(name); |
461 |
|
462 |
m_openElements.push(name); // must be encoded!
|
463 |
|
464 |
if (m_autoPad)
|
465 |
{ |
466 |
m_xml.append(m_pad); |
467 |
} |
468 |
|
469 |
m_xml.append("<");
|
470 |
m_xml.append(name); |
471 |
m_xml.append(" ");
|
472 |
|
473 |
Object elems[] = attributes.keySet().toArray(); |
474 |
|
475 |
for (int i = 0; i < elems.length; i++) |
476 |
{ |
477 |
String nm = (String)elems[i]; |
478 |
String val = (String)attributes.get(nm); |
479 |
|
480 |
encode(nm, m_xml); |
481 |
m_xml.append("=\"");
|
482 |
encode(val, m_xml); |
483 |
m_xml.append("\" ");
|
484 |
} |
485 |
|
486 |
m_xml.append(">");
|
487 |
|
488 |
if (m_autoPad)
|
489 |
{ |
490 |
m_padLevel++; |
491 |
|
492 |
if (m_padLevel < NUM_PADSTRINGS)
|
493 |
{ |
494 |
m_pad = s_padStrings[m_padLevel]; |
495 |
} |
496 |
else // really deep nesting level |
497 |
{ |
498 |
m_pad += PAD; |
499 |
} |
500 |
} |
501 |
} |
502 |
|
503 |
/**
|
504 |
* Closes an open tag.
|
505 |
*/
|
506 |
public void closeTag() |
507 |
{ |
508 |
if (m_autoPad)
|
509 |
{ |
510 |
if (m_padLevel > 0) |
511 |
{ |
512 |
m_padLevel--; |
513 |
} |
514 |
|
515 |
if (m_padLevel < NUM_PADSTRINGS)
|
516 |
{ |
517 |
m_pad = s_padStrings[m_padLevel]; |
518 |
} |
519 |
else // really deep nesting level |
520 |
{ |
521 |
int len = m_pad.length() - PAD.length();
|
522 |
if (len > 0) |
523 |
{ |
524 |
m_pad = m_pad.substring(0, len);
|
525 |
} |
526 |
} |
527 |
|
528 |
m_xml.append(m_pad); |
529 |
} |
530 |
|
531 |
String name = (String)m_openElements.pop(); // already encoded |
532 |
|
533 |
m_xml.append("</");
|
534 |
m_xml.append(name); |
535 |
m_xml.append(">");
|
536 |
} |
537 |
|
538 |
/**
|
539 |
* Get the xml.
|
540 |
*/
|
541 |
public String getXML() |
542 |
{ |
543 |
return m_xml.toString();
|
544 |
} |
545 |
|
546 |
/**
|
547 |
* Encodes the funny characters (e.g., '&', '<', '\"') in an XML
|
548 |
* string.
|
549 |
*
|
550 |
* @param src XML string to encode.
|
551 |
* @return the encoded string.
|
552 |
*/
|
553 |
private String encode(String src) |
554 |
{ |
555 |
m_encodeBuf.setLength(0); // clear old contents |
556 |
encode(src, m_encodeBuf); |
557 |
return m_encodeBuf.toString();
|
558 |
} |
559 |
|
560 |
/**
|
561 |
* Encodes the funny characters (e.g., '&', '<', '\"') in an XML
|
562 |
* string.
|
563 |
*
|
564 |
* @param src XML string to encode.
|
565 |
* @param dst string buffer to write the encoded XML string to.
|
566 |
*/
|
567 |
private static final void encode(String src, StringBuffer dst) |
568 |
{ |
569 |
int n = src.length();
|
570 |
|
571 |
for (int i = 0; i < n; i++) |
572 |
{ |
573 |
char c = src.charAt(i);
|
574 |
|
575 |
switch(c)
|
576 |
{ |
577 |
case '&': |
578 |
dst.append("&");
|
579 |
break;
|
580 |
case '<': |
581 |
dst.append("<");
|
582 |
break;
|
583 |
case '>': |
584 |
dst.append(">");
|
585 |
break;
|
586 |
case '\'': |
587 |
dst.append("'");
|
588 |
break;
|
589 |
case '\"': |
590 |
dst.append(""");
|
591 |
break;
|
592 |
case '\n': |
593 |
dst.append(s_newlineXmlEnc); |
594 |
break;
|
595 |
default:
|
596 |
dst.append(c); |
597 |
} |
598 |
} |
599 |
} |
600 |
} |
601 |
|