View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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("&lt;");
94                          break;
95                      case '>':
96                          _out.append("&gt;");
97                          break;
98                      case '&':
99                          _out.append("&amp;");
100                         break;
101                     case '\'':
102                         _out.append("&apos;");
103                         break;
104                     case '"':
105                         _out.append("&quot;");
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 }