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