View Javadoc

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