1 package org.apache.maven.archetype.common.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 import org.codehaus.plexus.util.StringUtils;
56 import org.jdom.Attribute;
57 import org.jdom.CDATA;
58 import org.jdom.Comment;
59 import org.jdom.DocType;
60 import org.jdom.Document;
61 import org.jdom.Element;
62 import org.jdom.EntityRef;
63 import org.jdom.Namespace;
64 import org.jdom.ProcessingInstruction;
65 import org.jdom.Text;
66 import org.jdom.output.EscapeStrategy;
67
68 import javax.xml.transform.Result;
69 import java.io.BufferedOutputStream;
70 import java.io.BufferedWriter;
71 import java.io.IOException;
72 import java.io.OutputStream;
73 import java.io.OutputStreamWriter;
74 import java.io.StringWriter;
75 import java.io.Writer;
76 import java.util.List;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 public class XMLOutputter
130 implements Cloneable
131 {
132
133 private Format userFormat = Format.getRawFormat();
134
135
136 protected static final Format preserveFormat = Format.getRawFormat();
137
138
139 protected Format currentFormat = userFormat;
140
141
142
143
144
145 private boolean escapeOutput = true;
146
147
148
149
150
151
152
153
154 public XMLOutputter()
155 {
156 }
157
158
159
160
161
162
163 public XMLOutputter( Format format )
164 {
165 userFormat = (Format) format.clone();
166 currentFormat = userFormat;
167 }
168
169
170
171
172
173
174
175
176
177 public XMLOutputter( XMLOutputter that )
178 {
179 this.userFormat = (Format) that.userFormat.clone();
180 currentFormat = userFormat;
181 }
182
183
184
185
186
187
188
189
190
191
192 public void setFormat( Format newFormat )
193 {
194 this.userFormat = (Format) newFormat.clone();
195 this.currentFormat = userFormat;
196 }
197
198
199
200
201
202 public Format getFormat()
203 {
204 return (Format) userFormat.clone();
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219 public void output( Document doc, OutputStream out )
220 throws IOException
221 {
222 Writer writer = makeWriter( out );
223 output( doc, writer );
224 }
225
226
227
228
229
230
231
232 public void output( DocType doctype, OutputStream out )
233 throws IOException
234 {
235 Writer writer = makeWriter( out );
236 output( doctype, writer );
237 }
238
239
240
241
242
243
244
245
246
247 public void output( Element element, OutputStream out )
248 throws IOException
249 {
250 Writer writer = makeWriter( out );
251 output( element, writer );
252 }
253
254
255
256
257
258
259
260
261
262
263
264 public void outputElementContent( Element element, OutputStream out )
265 throws IOException
266 {
267 Writer writer = makeWriter( out );
268 outputElementContent( element, writer );
269 }
270
271
272
273
274
275
276
277
278
279
280 public void output( List<?> list, OutputStream out )
281 throws IOException
282 {
283 Writer writer = makeWriter( out );
284 output( list, writer );
285 }
286
287
288
289
290
291
292
293 public void output( CDATA cdata, OutputStream out )
294 throws IOException
295 {
296 Writer writer = makeWriter( out );
297 output( cdata, writer );
298 }
299
300
301
302
303
304
305
306
307 public void output( Text text, OutputStream out )
308 throws IOException
309 {
310 Writer writer = makeWriter( out );
311 output( text, writer );
312 }
313
314
315
316
317
318
319
320 public void output( Comment comment, OutputStream out )
321 throws IOException
322 {
323 Writer writer = makeWriter( out );
324 output( comment, writer );
325 }
326
327
328
329
330
331
332
333 public void output( ProcessingInstruction pi, OutputStream out )
334 throws IOException
335 {
336 Writer writer = makeWriter( out );
337 output( pi, writer );
338 }
339
340
341
342
343
344
345
346 public void output( EntityRef entity, OutputStream out )
347 throws IOException
348 {
349 Writer writer = makeWriter( out );
350 output( entity, writer );
351 }
352
353
354
355
356
357 private Writer makeWriter( OutputStream out )
358 throws java.io.UnsupportedEncodingException
359 {
360 return makeWriter( out, userFormat.encoding );
361 }
362
363
364 private static Writer makeWriter( OutputStream out, String enc )
365 throws java.io.UnsupportedEncodingException
366 {
367
368
369 if ( "UTF-8".equals( enc ) )
370 {
371 enc = "UTF8";
372 }
373
374 Writer writer = new BufferedWriter( ( new OutputStreamWriter( new BufferedOutputStream( out ), enc ) ) );
375 return writer;
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 public void output( Document doc, Writer out )
394 throws IOException
395 {
396
397 printDeclaration( out, doc, userFormat.encoding );
398
399
400
401
402 List<?> content = doc.getContent();
403 int size = content.size();
404 for ( int i = 0; i < size; i++ )
405 {
406 Object obj = content.get( i );
407
408 if ( obj instanceof Element )
409 {
410 printElement( out, doc.getRootElement(), 0, createNamespaceStack() );
411 }
412 else if ( obj instanceof Comment )
413 {
414 printComment( out, (Comment) obj );
415 }
416 else if ( obj instanceof ProcessingInstruction )
417 {
418 printProcessingInstruction( out, (ProcessingInstruction) obj );
419 }
420 else if ( obj instanceof DocType )
421 {
422 printDocType( out, doc.getDocType() );
423
424
425 out.write( currentFormat.lineSeparator );
426 }
427 else
428 {
429
430
431 }
432
433 newline( out );
434 indent( out, 0 );
435 }
436
437
438
439 out.write( currentFormat.lineSeparator );
440
441 out.flush();
442 }
443
444
445
446
447
448
449
450 public void output( DocType doctype, Writer out )
451 throws IOException
452 {
453 printDocType( out, doctype );
454 out.flush();
455 }
456
457
458
459
460
461
462
463
464
465 public void output( Element element, Writer out )
466 throws IOException
467 {
468
469
470 printElement( out, element, 0, createNamespaceStack() );
471 out.flush();
472 }
473
474
475
476
477
478
479
480
481
482
483
484 public void outputElementContent( Element element, Writer out )
485 throws IOException
486 {
487 List<?> content = element.getContent();
488 printContentRange( out, content, 0, content.size(),
489 0, createNamespaceStack() );
490 out.flush();
491 }
492
493
494
495
496
497
498
499
500
501
502 public void output( List<?> list, Writer out )
503 throws IOException
504 {
505 printContentRange( out, list, 0, list.size(), 0, createNamespaceStack() );
506 out.flush();
507 }
508
509
510
511
512
513
514
515 public void output( CDATA cdata, Writer out )
516 throws IOException
517 {
518 printCDATA( out, cdata );
519 out.flush();
520 }
521
522
523
524
525
526
527
528
529 public void output( Text text, Writer out )
530 throws IOException
531 {
532 printText( out, text );
533 out.flush();
534 }
535
536
537
538
539
540
541
542 public void output( Comment comment, Writer out )
543 throws IOException
544 {
545 printComment( out, comment );
546 out.flush();
547 }
548
549
550
551
552
553
554
555 public void output( ProcessingInstruction pi, Writer out )
556 throws IOException
557 {
558 boolean currentEscapingPolicy = currentFormat.ignoreTrAXEscapingPIs;
559
560
561 currentFormat.setIgnoreTrAXEscapingPIs( true );
562 printProcessingInstruction( out, pi );
563 currentFormat.setIgnoreTrAXEscapingPIs( currentEscapingPolicy );
564
565 out.flush();
566 }
567
568
569
570
571
572
573
574 public void output( EntityRef entity, Writer out )
575 throws IOException
576 {
577 printEntityRef( out, entity );
578 out.flush();
579 }
580
581
582
583
584
585
586
587
588
589
590
591 public String outputString( Document doc )
592 {
593 StringWriter out = new StringWriter();
594 try
595 {
596 output( doc, out );
597 }
598 catch ( IOException e )
599 {
600 }
601 return out.toString();
602 }
603
604
605
606
607
608
609
610
611 public String outputString( DocType doctype )
612 {
613 StringWriter out = new StringWriter();
614 try
615 {
616 output( doctype, out );
617 }
618 catch ( IOException e )
619 {
620 }
621 return out.toString();
622 }
623
624
625
626
627
628
629
630
631 public String outputString( Element element )
632 {
633 StringWriter out = new StringWriter();
634 try
635 {
636 output( element, out );
637 }
638 catch ( IOException e )
639 {
640 }
641 return out.toString();
642 }
643
644
645
646
647
648
649
650 public String outputString( List<?> list )
651 {
652 StringWriter out = new StringWriter();
653 try
654 {
655 output( list, out );
656 }
657 catch ( IOException e )
658 {
659 }
660 return out.toString();
661 }
662
663
664
665
666
667
668
669
670 public String outputString( CDATA cdata )
671 {
672 StringWriter out = new StringWriter();
673 try
674 {
675 output( cdata, out );
676 }
677 catch ( IOException e )
678 {
679 }
680 return out.toString();
681 }
682
683
684
685
686
687
688
689
690 public String outputString( Text text )
691 {
692 StringWriter out = new StringWriter();
693 try
694 {
695 output( text, out );
696 }
697 catch ( IOException e )
698 {
699 }
700 return out.toString();
701 }
702
703
704
705
706
707
708
709
710
711 public String outputString( Comment comment )
712 {
713 StringWriter out = new StringWriter();
714 try
715 {
716 output( comment, out );
717 }
718 catch ( IOException e )
719 {
720 }
721 return out.toString();
722 }
723
724
725
726
727
728
729
730
731 public String outputString( ProcessingInstruction pi )
732 {
733 StringWriter out = new StringWriter();
734 try
735 {
736 output( pi, out );
737 }
738 catch ( IOException e )
739 {
740 }
741 return out.toString();
742 }
743
744
745
746
747
748
749
750
751 public String outputString( EntityRef entity )
752 {
753 StringWriter out = new StringWriter();
754 try
755 {
756 output( entity, out );
757 }
758 catch ( IOException e )
759 {
760 }
761 return out.toString();
762 }
763
764
765
766
767
768
769
770
771
772
773
774
775 protected void printDeclaration( Writer out, Document doc, String encoding )
776 throws IOException
777 {
778
779
780 if ( !userFormat.omitDeclaration )
781 {
782
783 out.write( "<?xml version=\"1.0\"" );
784 if ( !userFormat.omitEncoding )
785 {
786 out.write( " encoding=\"" + encoding + "\"" );
787 }
788 out.write( "?>" );
789
790
791
792
793 out.write( currentFormat.lineSeparator );
794 }
795 }
796
797
798
799
800
801
802
803 protected void printDocType( Writer out, DocType docType )
804 throws IOException
805 {
806
807 String publicID = docType.getPublicID();
808 String systemID = docType.getSystemID();
809 String internalSubset = docType.getInternalSubset();
810 boolean hasPublic = false;
811
812 out.write( "<!DOCTYPE " );
813 out.write( docType.getElementName() );
814 if ( publicID != null )
815 {
816 out.write( " PUBLIC \"" );
817 out.write( publicID );
818 out.write( "\"" );
819 hasPublic = true;
820 }
821 if ( systemID != null )
822 {
823 if ( !hasPublic )
824 {
825 out.write( " SYSTEM" );
826 }
827 out.write( " \"" );
828 out.write( systemID );
829 out.write( "\"" );
830 }
831 if ( ( internalSubset != null ) && ( !internalSubset.equals( "" ) ) )
832 {
833 out.write( " [" );
834 out.write( currentFormat.lineSeparator );
835 out.write( docType.getInternalSubset() );
836 out.write( "]" );
837 }
838 out.write( ">" );
839 }
840
841
842
843
844
845
846
847 protected void printComment( Writer out, Comment comment )
848 throws IOException
849 {
850 out.write( "<!--" );
851 out.write( StringUtils.unifyLineSeparators( comment.getText(), currentFormat.lineSeparator ) );
852 out.write( "-->" );
853 }
854
855
856
857
858
859
860
861 protected void printProcessingInstruction( Writer out, ProcessingInstruction pi )
862 throws IOException
863 {
864 String target = pi.getTarget();
865 boolean piProcessed = false;
866
867 if ( currentFormat.ignoreTrAXEscapingPIs == false )
868 {
869 if ( target.equals( Result.PI_DISABLE_OUTPUT_ESCAPING ) )
870 {
871 escapeOutput = false;
872 piProcessed = true;
873 }
874 else if ( target.equals( Result.PI_ENABLE_OUTPUT_ESCAPING ) )
875 {
876 escapeOutput = true;
877 piProcessed = true;
878 }
879 }
880 if ( piProcessed == false )
881 {
882 String rawData = pi.getData();
883
884
885 if ( !"".equals( rawData ) )
886 {
887 out.write( "<?" );
888 out.write( target );
889 out.write( " " );
890 out.write( rawData );
891 out.write( "?>" );
892 }
893 else
894 {
895 out.write( "<?" );
896 out.write( target );
897 out.write( "?>" );
898 }
899 }
900 }
901
902
903
904
905
906
907
908
909
910
911 protected void printEntityRef( Writer out, EntityRef entity )
912 throws IOException
913 {
914 out.write( "&" );
915 out.write( entity.getName() );
916 out.write( ";" );
917 }
918
919
920
921
922
923
924
925 protected void printCDATA( Writer out, CDATA cdata )
926 throws IOException
927 {
928 String str =
929 ( currentFormat.mode == Format.TextMode.NORMALIZE ) ? cdata.getTextNormalize()
930 : ( ( currentFormat.mode == Format.TextMode.TRIM ) ? cdata.getText().trim()
931 : cdata.getText() );
932 out.write( "<![CDATA[" );
933 out.write( str );
934 out.write( "]]>" );
935 }
936
937
938
939
940
941
942
943 protected void printText( Writer out, Text text )
944 throws IOException
945 {
946 String str =
947 ( currentFormat.mode == Format.TextMode.NORMALIZE ) ? text.getTextNormalize()
948 : ( ( currentFormat.mode == Format.TextMode.TRIM ) ? text.getText().trim() : text.getText() );
949 out.write( escapeElementEntities( str ) );
950 }
951
952
953
954
955
956 private void printString( Writer out, String str )
957 throws IOException
958 {
959 if ( currentFormat.mode == Format.TextMode.NORMALIZE )
960 {
961 str = Text.normalizeString( str );
962 }
963 else if ( currentFormat.mode == Format.TextMode.TRIM )
964 {
965 str = str.trim();
966 }
967 out.write( escapeElementEntities( str ) );
968 }
969
970
971
972
973
974
975
976
977
978
979
980 protected void printElement( Writer out, Element element, int level, NamespaceStack namespaces )
981 throws IOException
982 {
983
984 List<?> attributes = element.getAttributes();
985 List<?> content = element.getContent();
986
987
988 String space = null;
989 if ( attributes != null )
990 {
991 space = element.getAttributeValue( "space", Namespace.XML_NAMESPACE );
992 }
993
994 Format previousFormat = currentFormat;
995
996 if ( "default".equals( space ) )
997 {
998 currentFormat = userFormat;
999 }
1000 else if ( "preserve".equals( space ) )
1001 {
1002 currentFormat = preserveFormat;
1003 }
1004
1005
1006
1007 out.write( "<" );
1008 printQualifiedName( out, element );
1009
1010
1011 int previouslyDeclaredNamespaces = namespaces.size();
1012
1013
1014 printElementNamespace( out, element, namespaces );
1015
1016
1017 printAdditionalNamespaces( out, element, namespaces );
1018
1019
1020 if ( attributes != null )
1021 {
1022 printAttributes( out, attributes, element, namespaces );
1023 }
1024
1025
1026
1027
1028
1029
1030 int start = skipLeadingWhite( content, 0 );
1031 int size = content.size();
1032 if ( start >= size )
1033 {
1034
1035 if ( currentFormat.expandEmptyElements )
1036 {
1037 out.write( "></" );
1038 printQualifiedName( out, element );
1039 out.write( ">" );
1040 }
1041 else
1042 {
1043 out.write( " />" );
1044 }
1045 }
1046 else
1047 {
1048 out.write( ">" );
1049
1050
1051
1052
1053
1054 if ( nextNonText( content, start ) < size )
1055 {
1056
1057 newline( out );
1058 printContentRange( out, content, start, size,
1059 level + 1, namespaces );
1060 newline( out );
1061 indent( out, level );
1062 }
1063 else
1064 {
1065
1066 printTextRange( out, content, start, size );
1067 }
1068 out.write( "</" );
1069 printQualifiedName( out, element );
1070 out.write( ">" );
1071 }
1072
1073
1074 while ( namespaces.size() > previouslyDeclaredNamespaces )
1075 {
1076 namespaces.pop();
1077 }
1078
1079
1080 currentFormat = previousFormat;
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096 private void printContentRange( Writer out, List<?> content, int start, int end, int level, NamespaceStack namespaces )
1097 throws IOException
1098 {
1099 boolean firstNode;
1100 Object next;
1101 int first, index;
1102
1103 index = start;
1104 while ( index < end )
1105 {
1106 firstNode = ( index == start ) ? true : false;
1107 next = content.get( index );
1108
1109
1110
1111
1112 if ( ( next instanceof Text ) || ( next instanceof EntityRef ) )
1113 {
1114 first = skipLeadingWhite( content, index );
1115
1116 index = nextNonText( content, first );
1117
1118
1119 if ( first < index )
1120 {
1121 if ( !firstNode )
1122 {
1123 newline( out );
1124 }
1125 indent( out, level );
1126 printTextRange( out, content, first, index );
1127 }
1128 continue;
1129 }
1130
1131
1132
1133
1134 if ( !firstNode )
1135 {
1136 newline( out );
1137 }
1138
1139 indent( out, level );
1140
1141 if ( next instanceof Comment )
1142 {
1143 printComment( out, (Comment) next );
1144 }
1145 else if ( next instanceof Element )
1146 {
1147 printElement( out, (Element) next, level, namespaces );
1148 }
1149 else if ( next instanceof ProcessingInstruction )
1150 {
1151 printProcessingInstruction( out, (ProcessingInstruction) next );
1152 }
1153 else
1154 {
1155
1156
1157
1158 }
1159
1160 index++;
1161 }
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 private void printTextRange( Writer out, List<?> content, int start, int end )
1175 throws IOException
1176 {
1177 String previous;
1178 Object node;
1179 String next;
1180
1181 previous = null;
1182
1183
1184 start = skipLeadingWhite( content, start );
1185
1186 int size = content.size();
1187 if ( start < size )
1188 {
1189
1190 end = skipTrailingWhite( content, end );
1191
1192 for ( int i = start; i < end; i++ )
1193 {
1194 node = content.get( i );
1195
1196
1197
1198 if ( node instanceof CDATA )
1199 {
1200 next = "<![CDATA[" + ( (CDATA) node ).getValue() + "]]>";
1201 }
1202 else if ( node instanceof Text )
1203 {
1204 next = ( (Text) node ).getText();
1205 }
1206 else if ( node instanceof EntityRef )
1207 {
1208 next = "&" + ( (EntityRef) node ).getValue() + ";";
1209 }
1210 else
1211 {
1212 throw new IllegalStateException( "Should see only CDATA, Text, or EntityRef" );
1213 }
1214
1215
1216 if ( next == null || "".equals( next ) )
1217 {
1218 continue;
1219 }
1220
1221
1222
1223 if ( previous != null )
1224 {
1225 if ( currentFormat.mode == Format.TextMode.NORMALIZE
1226 || currentFormat.mode == Format.TextMode.TRIM )
1227 {
1228 if ( ( endsWithWhite( previous ) )
1229 || ( startsWithWhite( next ) ) )
1230 {
1231 out.write( " " );
1232 }
1233 }
1234 }
1235
1236
1237 if ( node instanceof CDATA )
1238 {
1239 printCDATA( out, (CDATA) node );
1240 }
1241 else if ( node instanceof EntityRef )
1242 {
1243 printEntityRef( out, (EntityRef) node );
1244 }
1245 else
1246 {
1247 printString( out, next );
1248 }
1249
1250 previous = next;
1251 }
1252 }
1253 }
1254
1255
1256
1257
1258
1259
1260
1261
1262 private void printNamespace( Writer out, Namespace ns, NamespaceStack namespaces )
1263 throws IOException
1264 {
1265 String prefix = ns.getPrefix();
1266 String uri = ns.getURI();
1267
1268
1269 if ( uri.equals( namespaces.getURI( prefix ) ) )
1270 {
1271 return;
1272 }
1273
1274 out.write( " xmlns" );
1275 if ( !prefix.equals( "" ) )
1276 {
1277 out.write( ":" );
1278 out.write( prefix );
1279 }
1280 out.write( "=\"" );
1281 out.write( uri );
1282 out.write( "\"" );
1283 namespaces.push( ns );
1284 }
1285
1286
1287
1288
1289
1290
1291
1292 protected void printAttributes( Writer out, List<?> attributes, Element parent, NamespaceStack namespaces )
1293 throws IOException
1294 {
1295
1296
1297
1298
1299
1300
1301 for ( int i = 0; i < attributes.size(); i++ )
1302 {
1303 Attribute attribute = (Attribute) attributes.get( i );
1304 Namespace ns = attribute.getNamespace();
1305 if ( ( ns != Namespace.NO_NAMESPACE ) && ( ns != Namespace.XML_NAMESPACE ) )
1306 {
1307 printNamespace( out, ns, namespaces );
1308 }
1309
1310 out.write( " " );
1311 printQualifiedName( out, attribute );
1312 out.write( "=" );
1313
1314 out.write( "\"" );
1315 out.write( escapeAttributeEntities( attribute.getValue() ) );
1316 out.write( "\"" );
1317 }
1318 }
1319
1320 private void printElementNamespace( Writer out, Element element, NamespaceStack namespaces )
1321 throws IOException
1322 {
1323
1324
1325
1326
1327 Namespace ns = element.getNamespace();
1328 if ( ns == Namespace.XML_NAMESPACE )
1329 {
1330 return;
1331 }
1332 if ( !( ( ns == Namespace.NO_NAMESPACE ) && ( namespaces.getURI( "" ) == null ) ) )
1333 {
1334 printNamespace( out, ns, namespaces );
1335 }
1336 }
1337
1338 private void printAdditionalNamespaces( Writer out, Element element, NamespaceStack namespaces )
1339 throws IOException
1340 {
1341 List<?> list = element.getAdditionalNamespaces();
1342 if ( list != null )
1343 {
1344 for ( int i = 0; i < list.size(); i++ )
1345 {
1346 Namespace additional = (Namespace) list.get( i );
1347 printNamespace( out, additional, namespaces );
1348 }
1349 }
1350 }
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361 private void newline( Writer out )
1362 throws IOException
1363 {
1364 if ( currentFormat.indent != null )
1365 {
1366 out.write( currentFormat.lineSeparator );
1367 }
1368 }
1369
1370
1371
1372
1373
1374
1375
1376
1377 private void indent( Writer out, int level )
1378 throws IOException
1379 {
1380 if ( currentFormat.indent == null || currentFormat.indent.equals( "" ) )
1381 {
1382 return;
1383 }
1384
1385 for ( int i = 0; i < level; i++ )
1386 {
1387 out.write( currentFormat.indent );
1388 }
1389 }
1390
1391
1392
1393
1394
1395 private int skipLeadingWhite( List<?> content, int start )
1396 {
1397 if ( start < 0 )
1398 {
1399 start = 0;
1400 }
1401
1402 int index = start;
1403 int size = content.size();
1404 if ( currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
1405 || currentFormat.mode == Format.TextMode.NORMALIZE
1406 || currentFormat.mode == Format.TextMode.TRIM )
1407 {
1408 while ( index < size )
1409 {
1410 if ( !isAllWhitespace( content.get( index ) ) )
1411 {
1412 return index;
1413 }
1414 index++;
1415 }
1416 }
1417 return index;
1418 }
1419
1420
1421
1422
1423
1424 private int skipTrailingWhite( List<?> content, int start )
1425 {
1426 int size = content.size();
1427 if ( start > size )
1428 {
1429 start = size;
1430 }
1431
1432 int index = start;
1433 if ( currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
1434 || currentFormat.mode == Format.TextMode.NORMALIZE
1435 || currentFormat.mode == Format.TextMode.TRIM )
1436 {
1437 while ( index >= 0 )
1438 {
1439 if ( !isAllWhitespace( content.get( index - 1 ) ) )
1440 {
1441 break;
1442 }
1443 --index;
1444 }
1445 }
1446 return index;
1447 }
1448
1449
1450
1451
1452
1453 private static int nextNonText( List<?> content, int start )
1454 {
1455 if ( start < 0 )
1456 {
1457 start = 0;
1458 }
1459
1460 int index = start;
1461 int size = content.size();
1462 while ( index < size )
1463 {
1464 Object node = content.get( index );
1465 if ( !( ( node instanceof Text ) || ( node instanceof EntityRef ) ) )
1466 {
1467 return index;
1468 }
1469 index++;
1470 }
1471 return size;
1472 }
1473
1474
1475 private boolean isAllWhitespace( Object obj )
1476 {
1477 String str = null;
1478
1479 if ( obj instanceof String )
1480 {
1481 str = (String) obj;
1482 }
1483 else if ( obj instanceof Text )
1484 {
1485 str = ( (Text) obj ).getText();
1486 }
1487 else if ( obj instanceof EntityRef )
1488 {
1489 return false;
1490 }
1491 else
1492 {
1493 return false;
1494 }
1495
1496 for ( int i = 0; i < str.length(); i++ )
1497 {
1498 if ( !isWhitespace( str.charAt( i ) ) )
1499 {
1500 return false;
1501 }
1502 }
1503 return true;
1504 }
1505
1506
1507 private boolean startsWithWhite( String str )
1508 {
1509 return ( ( str != null ) && ( str.length() > 0 ) && isWhitespace( str.charAt( 0 ) ) );
1510 }
1511
1512
1513 private boolean endsWithWhite( String str )
1514 {
1515 return ( ( str != null ) && ( str.length() > 0 ) && isWhitespace( str.charAt( str.length() - 1 ) ) );
1516 }
1517
1518
1519
1520 private static boolean isWhitespace( char c )
1521 {
1522 return ( c == ' ' || c == '\n' || c == '\t' || c == '\r' );
1523 }
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535 public String escapeAttributeEntities( String str )
1536 {
1537 StringBuilder buffer;
1538 char ch;
1539 String entity;
1540 EscapeStrategy strategy = currentFormat.escapeStrategy;
1541
1542 buffer = null;
1543 for ( int i = 0; i < str.length(); i++ )
1544 {
1545 ch = str.charAt( i );
1546 switch ( ch )
1547 {
1548 case '<':
1549 entity = "<";
1550 break;
1551 case '>':
1552 entity = ">";
1553 break;
1554
1555
1556
1557
1558
1559 case '\"':
1560 entity = """;
1561 break;
1562 case '&':
1563 entity = "&";
1564 break;
1565 case '\r':
1566 entity = "
";
1567 break;
1568 case '\t':
1569 entity = "	";
1570 break;
1571 case '\n':
1572 entity = "
";
1573 break;
1574 default:
1575 if ( strategy.shouldEscape( ch ) )
1576 {
1577 entity = "&#x" + Integer.toHexString( ch ) + ";";
1578 }
1579 else
1580 {
1581 entity = null;
1582 }
1583 break;
1584 }
1585 if ( buffer == null )
1586 {
1587 if ( entity != null )
1588 {
1589
1590
1591 buffer = new StringBuilder( str.length() + 20 );
1592
1593
1594 buffer.append( str.substring( 0, i ) );
1595 buffer.append( entity );
1596 }
1597 }
1598 else
1599 {
1600 if ( entity == null )
1601 {
1602 buffer.append( ch );
1603 }
1604 else
1605 {
1606 buffer.append( entity );
1607 }
1608 }
1609 }
1610
1611
1612
1613
1614 return ( buffer == null ) ? str : buffer.toString();
1615 }
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627 public String escapeElementEntities( String str )
1628 {
1629 if ( escapeOutput == false )
1630 {
1631 return str;
1632 }
1633
1634 StringBuilder buffer;
1635 char ch;
1636 String entity;
1637 EscapeStrategy strategy = currentFormat.escapeStrategy;
1638
1639 buffer = null;
1640 for ( int i = 0; i < str.length(); i++ )
1641 {
1642 ch = str.charAt( i );
1643 switch ( ch )
1644 {
1645 case '<':
1646 entity = "<";
1647 break;
1648 case '>':
1649 entity = ">";
1650 break;
1651 case '&':
1652 entity = "&";
1653 break;
1654 case '\r':
1655 entity = "
";
1656 break;
1657 case '\n':
1658 entity = currentFormat.lineSeparator;
1659 break;
1660 default:
1661 if ( strategy.shouldEscape( ch ) )
1662 {
1663 entity = "&#x" + Integer.toHexString( ch ) + ";";
1664 }
1665 else
1666 {
1667 entity = null;
1668 }
1669 break;
1670 }
1671 if ( buffer == null )
1672 {
1673 if ( entity != null )
1674 {
1675
1676
1677 buffer = new StringBuilder( str.length() + 20 );
1678
1679
1680 buffer.append( str.substring( 0, i ) );
1681 buffer.append( entity );
1682 }
1683 }
1684 else
1685 {
1686 if ( entity == null )
1687 {
1688 buffer.append( ch );
1689 }
1690 else
1691 {
1692 buffer.append( entity );
1693 }
1694 }
1695 }
1696
1697
1698
1699
1700 return ( buffer == null ) ? str : buffer.toString();
1701 }
1702
1703
1704 @Override
1705 public Object clone()
1706 {
1707
1708
1709
1710
1711
1712 try
1713 {
1714 return super.clone();
1715 }
1716 catch ( java.lang.CloneNotSupportedException e )
1717 {
1718
1719
1720
1721
1722 throw new RuntimeException( e.toString() );
1723 }
1724 }
1725
1726
1727
1728
1729
1730
1731
1732 @Override
1733 public String toString()
1734 {
1735 StringBuilder buffer = new StringBuilder();
1736 for ( int i = 0; i < userFormat.lineSeparator.length(); i++ )
1737 {
1738 char ch = userFormat.lineSeparator.charAt( i );
1739 switch ( ch )
1740 {
1741 case '\r':
1742 buffer.append( "\\r" );
1743 break;
1744 case '\n':
1745 buffer.append( "\\n" );
1746 break;
1747 case '\t':
1748 buffer.append( "\\t" );
1749 break;
1750 default:
1751 buffer.append( "[" + ( (int) ch ) + "]" );
1752 break;
1753 }
1754 }
1755
1756 return (
1757 "XMLOutputter[omitDeclaration = " + userFormat.omitDeclaration + ", "
1758 + "encoding = " + userFormat.encoding + ", "
1759 + "omitEncoding = " + userFormat.omitEncoding + ", "
1760 + "indent = '" + userFormat.indent + "'" + ", "
1761 + "expandEmptyElements = " + userFormat.expandEmptyElements + ", "
1762 + "lineSeparator = '" + buffer.toString() + "', "
1763 + "textMode = " + userFormat.mode + "]"
1764 );
1765 }
1766
1767
1768
1769
1770
1771
1772
1773 private NamespaceStack createNamespaceStack()
1774 {
1775
1776 return new NamespaceStack();
1777 }
1778
1779
1780
1781
1782
1783
1784
1785
1786 protected class NamespaceStack
1787 extends org.apache.maven.archetype.common.util.NamespaceStack
1788 {
1789 }
1790
1791
1792
1793 private void printQualifiedName( Writer out, Element e )
1794 throws IOException
1795 {
1796 if ( e.getNamespace().getPrefix().length() == 0 )
1797 {
1798 out.write( e.getName() );
1799 }
1800 else
1801 {
1802 out.write( e.getNamespace().getPrefix() );
1803 out.write( ':' );
1804 out.write( e.getName() );
1805 }
1806 }
1807
1808
1809
1810 private void printQualifiedName( Writer out, Attribute a )
1811 throws IOException
1812 {
1813 String prefix = a.getNamespace().getPrefix();
1814 if ( ( prefix != null ) && ( !prefix.equals( "" ) ) )
1815 {
1816 out.write( prefix );
1817 out.write( ':' );
1818 out.write( a.getName() );
1819 }
1820 else
1821 {
1822 out.write( a.getName() );
1823 }
1824 }
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835 }