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