1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.xml;
20
21 import java.io.Closeable;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.io.OutputStreamWriter;
25 import java.io.PrintWriter;
26 import java.util.Map;
27 import java.util.Stack;
28
29 public class XmlAppendable
30 {
31 private final String SPACES=" ";
32 private final Appendable _out;
33 private final int _indent;
34 private final Stack<String> _tags = new Stack<>();
35 private String _space="";
36
37 public XmlAppendable(OutputStream out,String encoding) throws IOException
38 {
39 this(new OutputStreamWriter(out,encoding),encoding);
40 }
41
42 public XmlAppendable(Appendable out) throws IOException
43 {
44 this(out,2);
45 }
46
47 public XmlAppendable(Appendable out,String encoding) throws IOException
48 {
49 this(out,2,encoding);
50 }
51
52 public XmlAppendable(Appendable out, int indent) throws IOException
53 {
54 this(out,indent,"UTF-8");
55 }
56
57 public XmlAppendable(Appendable out, int indent, String encoding) throws IOException
58 {
59 _out=out;
60 _indent=indent;
61 _out.append("<?xml version=\"1.0\" encoding=\""+encoding+"\"?>\n");
62 }
63
64 public XmlAppendable open(String tag, Map<String,String> attributes) throws IOException
65 {
66 _out.append(_space).append('<').append(tag);
67 attributes(attributes);
68
69 _out.append(">\n");
70 _space=_space+SPACES.substring(0,_indent);
71 _tags.push(tag);
72 return this;
73 }
74
75 public XmlAppendable open(String tag) throws IOException
76 {
77 _out.append(_space).append('<').append(tag).append(">\n");
78 _space=_space+SPACES.substring(0,_indent);
79 _tags.push(tag);
80 return this;
81 }
82
83 public XmlAppendable content(String s) throws IOException
84 {
85 if (s!=null)
86 {
87 for (int i=0;i<s.length();i++)
88 {
89 char c = s.charAt(i);
90 switch(c)
91 {
92 case '<':
93 _out.append("<");
94 break;
95 case '>':
96 _out.append(">");
97 break;
98 case '&':
99 _out.append("&");
100 break;
101 case '\'':
102 _out.append("'");
103 break;
104 case '"':
105 _out.append(""");
106 break;
107 default:
108 _out.append(c);
109 }
110 }
111 }
112
113 return this;
114 }
115
116 public XmlAppendable cdata(String s) throws IOException
117 {
118 _out.append("<![CDATA[").append(s).append("]]>");
119 return this;
120 }
121
122 public XmlAppendable tag(String tag) throws IOException
123 {
124 _out.append(_space).append('<').append(tag).append("/>\n");
125 return this;
126 }
127
128 public XmlAppendable tag(String tag, Map<String,String> attributes) throws IOException
129 {
130 _out.append(_space).append('<').append(tag);
131 attributes(attributes);
132 _out.append("/>\n");
133 return this;
134 }
135
136 public XmlAppendable tag(String tag,String content) throws IOException
137 {
138 _out.append(_space).append('<').append(tag).append('>');
139 content(content);
140 _out.append("</").append(tag).append(">\n");
141 return this;
142 }
143
144 public XmlAppendable tagCDATA(String tag,String data) throws IOException
145 {
146 _out.append(_space).append('<').append(tag).append('>');
147 cdata(data);
148 _out.append("</").append(tag).append(">\n");
149 return this;
150 }
151
152 public XmlAppendable tag(String tag, Map<String,String> attributes,String content) throws IOException
153 {
154 _out.append(_space).append('<').append(tag);
155 attributes(attributes);
156 _out.append('>');
157 content(content);
158 _out.append("</").append(tag).append(">\n");
159 return this;
160 }
161
162 public XmlAppendable close() throws IOException
163 {
164 if (_tags.isEmpty())
165 throw new IllegalStateException("Tags closed");
166 String tag=_tags.pop();
167 _space=_space.substring(0,_space.length()-_indent);
168 _out.append(_space).append("</").append(tag).append(">\n");
169 if (_tags.isEmpty() && _out instanceof Closeable)
170 ((Closeable)_out).close();
171 return this;
172 }
173
174 private void attributes(Map<String,String> attributes) throws IOException
175 {
176 for (String k:attributes.keySet())
177 {
178 String v = attributes.get(k);
179 _out.append(' ').append(k).append("=\"");
180 content(v);
181 _out.append('"');
182 }
183 }
184
185 public void literal(String xml) throws IOException
186 {
187 _out.append(xml);
188 }
189
190 }