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