1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util.xml;
24  
25  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
26  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.portal.kernel.util.Validator;
30  
31  import java.io.IOException;
32  
33  import org.dom4j.Branch;
34  import org.dom4j.Document;
35  import org.dom4j.DocumentException;
36  import org.dom4j.io.OutputFormat;
37  import org.dom4j.io.SAXReader;
38  import org.dom4j.io.XMLWriter;
39  
40  /**
41   * <a href="XMLFormatter.java.html"><b><i>View Source</i></b></a>
42   *
43   * @author Brian Wing Shun Chan
44   * @author Alan Zimmerman
45   */
46  public class XMLFormatter {
47  
48      public static String fixProlog(String xml) {
49  
50          // LEP-1921
51  
52          if (xml != null) {
53              char[] charArray = xml.toCharArray();
54  
55              for (int i = 0; i < charArray.length; i++) {
56                  if (charArray[i] == '<') {
57                      if (i != 0) {
58                          xml = xml.substring(i, xml.length());
59                      }
60  
61                      break;
62                  }
63              }
64          }
65  
66          return xml;
67      }
68  
69      public static String fromCompactSafe(String xml) {
70          return StringUtil.replace(xml, "[$NEW_LINE$]", StringPool.NEW_LINE);
71      }
72  
73      public static String stripInvalidChars(String xml) {
74          if (Validator.isNull(xml)) {
75              return xml;
76          }
77  
78          // Strip characters that are not valid in the 1.0 XML spec
79          // http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char
80  
81          StringBuilder sb = new StringBuilder();
82  
83          for (int i = 0; i < xml.length(); i++) {
84              char c = xml.charAt(i);
85  
86              if ((c == 0x9) || (c == 0xA) || (c == 0xD) ||
87                  ((c >= 0x20) && (c <= 0xD7FF)) ||
88                  ((c >= 0xE000) && (c <= 0xFFFD)) ||
89                  ((c >= 0x10000) && (c <= 0x10FFFF))) {
90  
91                  sb.append(c);
92              }
93          }
94  
95          return sb.toString();
96      }
97  
98      public static String toCompactSafe(String xml) {
99          return StringUtil.replace(
100             xml,
101             new String[] {
102                 StringPool.RETURN_NEW_LINE,
103                 StringPool.NEW_LINE,
104                 StringPool.RETURN
105             },
106             new String[] {
107                 "[$NEW_LINE$]",
108                 "[$NEW_LINE$]",
109                 "[$NEW_LINE$]"
110             });
111     }
112 
113     public static String toString(Branch branch) throws IOException {
114         return toString(branch, StringPool.TAB);
115     }
116 
117     public static String toString(Branch branch, String indent)
118         throws IOException {
119 
120         return toString(branch, StringPool.TAB, false);
121     }
122 
123     public static String toString(
124             Branch branch, String indent, boolean expandEmptyElements)
125         throws IOException {
126 
127         UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
128             new UnsyncByteArrayOutputStream();
129 
130         OutputFormat outputFormat = OutputFormat.createPrettyPrint();
131 
132         outputFormat.setExpandEmptyElements(expandEmptyElements);
133         outputFormat.setIndent(indent);
134         outputFormat.setLineSeparator(StringPool.NEW_LINE);
135 
136         XMLWriter writer = new XMLWriter(
137             unsyncByteArrayOutputStream, outputFormat);
138 
139         writer.write(branch);
140 
141         String content = unsyncByteArrayOutputStream.toString(StringPool.UTF8);
142 
143         // LEP-4257
144 
145         //content = StringUtil.replace(content, "\n\n\n", "\n\n");
146 
147         if (content.endsWith("\n\n")) {
148             content = content.substring(0, content.length() - 2);
149         }
150 
151         if (content.endsWith("\n")) {
152             content = content.substring(0, content.length() - 1);
153         }
154 
155         while (content.indexOf(" \n") != -1) {
156             content = StringUtil.replace(content, " \n", "\n");
157         }
158 
159         return content;
160     }
161 
162     public static String toString(String xml)
163         throws DocumentException, IOException {
164 
165         return toString(xml, StringPool.TAB);
166     }
167 
168     public static String toString(String xml, String indent)
169         throws DocumentException, IOException {
170 
171         SAXReader reader = new SAXReader();
172 
173         Document doc = reader.read(new UnsyncStringReader(xml));
174 
175         return toString(doc, indent);
176     }
177 
178 }