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.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("&lt;");
93                          break;
94                      case '>':
95                          _out.append("&gt;");
96                          break;
97                      case '&':
98                          _out.append("&amp;");
99                          break;
100                     case '\'':
101                         _out.append("&apos;");
102                         break;
103                     case '"':
104                         _out.append("&quot;");
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 }