PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/XML/xml/indent/IndentingTransformerImpl.java

#
Java | 352 lines | 190 code | 106 blank | 56 comment | 34 complexity | c4c6f73a585b1a476de0722feb7087bc MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * IndentingTransformerImpl.java - Indents XML elements, by adding whitespace where appropriate.
  3. *
  4. * Copyright (c) 2002, 2003 Robert McKinnon
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. *
  20. * email: robmckinnon@users.sourceforge.net
  21. */
  22. package xml.indent;
  23. import org.xml.sax.Attributes;
  24. import org.xml.sax.Locator;
  25. import org.xml.sax.SAXException;
  26. import javax.xml.transform.Result;
  27. import javax.xml.transform.Transformer;
  28. import java.util.List;
  29. import java.io.Writer;
  30. import java.io.IOException;
  31. /**
  32. * Indents elements, by adding whitespace where appropriate.
  33. * Does not remove blank lines between nodes.
  34. * Does not remove new lines within text nodes.
  35. * Puts element tags immediately following mixed content text on the same line as the text.
  36. *
  37. * @author Robert McKinnon - robmckinnon@users.sourceforge.net
  38. */
  39. public class IndentingTransformerImpl extends IndentingTransformer {
  40. private List preserveWhitespaceList;
  41. /** indent by this many spaces */
  42. private int indentAmount = 2;
  43. /** indent with tabs instead of spaces */
  44. private char indentChar;
  45. /** current indentation level */
  46. private int indentLevel;
  47. // /** true if the previous tag was an element start tag */
  48. // private boolean isStartTagPrevious = false;
  49. /** true if no newlines in element */
  50. private boolean isSameLine;
  51. /** true if last item was non-whitespace text */
  52. private boolean isLastText;
  53. /** true if there is a non-whitespace text item, followed by an element start */
  54. private boolean isMixedContent;
  55. /** true if inside an element configured to have whitespace preserved */
  56. private boolean preserveWhitespace;
  57. /** name of element we are inside that is configured to have whitespace preserved */
  58. private String preserveWhitespaceElement;
  59. /** buffer to hold character data */
  60. private StringBuffer buffer = new StringBuffer();
  61. public String indentXml(String xmlString, Writer outputWriter, int indentAmount, boolean indentWithTabs, List preserveWhitespaceList)
  62. throws IOException, SAXException {
  63. this.preserveWhitespaceList = preserveWhitespaceList;
  64. this.indentAmount = indentAmount;
  65. if(indentWithTabs) {
  66. this.indentChar = '\t';
  67. } else {
  68. this.indentChar = ' ';
  69. }
  70. indentLevel = 0;
  71. isSameLine = false;
  72. isLastText = false;
  73. isMixedContent = false;
  74. preserveWhitespace = false;
  75. preserveWhitespaceElement = null;
  76. buffer.setLength(0);
  77. return super.indentXml(xmlString, outputWriter);
  78. }
  79. public Transformer getTransformer() {
  80. return null;
  81. }
  82. public void startElement(String uri, String localName, String qualifiedName, Attributes attributes) throws SAXException {
  83. flush();
  84. if(preserveWhitespaceList.contains(qualifiedName)) {
  85. preserveWhitespace = true;
  86. preserveWhitespaceElement = qualifiedName;
  87. }
  88. if(isLastText && !isMixedContent) {
  89. isMixedContent = true;
  90. }
  91. if(!isMixedContent) {
  92. indent(0);
  93. }
  94. super.startElement(uri, localName, qualifiedName, attributes);
  95. // isStartTagPrevious = true;
  96. indentLevel++;
  97. isSameLine = true; // assume a single line of content
  98. }
  99. public void endElement(String uri, String localName, String qualifiedName) throws SAXException {
  100. // boolean tempIsLastText = isLastText;
  101. // if(isStartTagPrevious) {
  102. // isLastText = true;
  103. // }
  104. flush();
  105. // if(isStartTagPrevious) {
  106. // isLastText = tempIsLastText;
  107. // }
  108. indentLevel--;
  109. if(!isMixedContent && !isSameLine && !isLastText) {
  110. indent(0);
  111. }
  112. super.endElement(uri, localName, qualifiedName);
  113. // isStartTagPrevious = false;
  114. isLastText = false;
  115. isSameLine = false;
  116. isMixedContent = false;
  117. if(qualifiedName.equals(preserveWhitespaceElement)) {
  118. preserveWhitespace = false;
  119. preserveWhitespaceElement = null;
  120. }
  121. }
  122. public void processingInstruction(String target, String data) throws SAXException {
  123. flush();
  124. indent(0);
  125. super.processingInstruction(target, data);
  126. }
  127. public void characters(char[] chars, int start, int length) throws SAXException {
  128. for(int i = start; i < start + length; i++) {
  129. if(!Character.isWhitespace(chars[i])) {
  130. isLastText = true;
  131. }
  132. }
  133. if(preserveWhitespace) {
  134. isLastText = true;
  135. }
  136. buffer.append(chars, start, length);
  137. }
  138. public void comment(char[] chars, int start, int len) throws SAXException {
  139. isLastText = true;
  140. flush();
  141. super.comment(chars, start, len);
  142. isLastText = false;
  143. }
  144. /**
  145. * Output white space to reflect the current indentation level
  146. */
  147. protected void indent(int levelAdjustment) throws SAXException {
  148. int arraySize = (indentLevel + levelAdjustment) * indentAmount + 1;
  149. arraySize = arraySize <= 0 ? 1 : arraySize;
  150. char[] indent = new char[arraySize];
  151. indent[0] = '\n';
  152. for(int i = 1; i < indent.length; i++) {
  153. indent[i] = indentChar;
  154. }
  155. super.characters(indent, 0, indent.length);
  156. }
  157. /**
  158. * Flush the buffer containing accumulated character data.
  159. * White space adjacent to markup is trimmed.
  160. */
  161. public void flush() throws SAXException {
  162. int end = buffer.length();
  163. int start = 0;
  164. if(end != 0) {
  165. char[] array = new char[end];
  166. buffer.getChars(0, end, array, 0);
  167. if(!isLastText) {
  168. boolean stripNewLineFromStart = true;
  169. while(start < end && Character.isWhitespace(array[start])) {
  170. if(Character.isSpaceChar(array[start]) || array[start] == '\t') {
  171. start++;
  172. } else if(stripNewLineFromStart) {
  173. start++;
  174. stripNewLineFromStart = false;
  175. } else {
  176. break;
  177. }
  178. }
  179. if(start < end && Character.isWhitespace(array[end - 1])) {
  180. while(start < end && Character.isWhitespace(array[end - 1])) {
  181. if(Character.isSpaceChar(array[end - 1]) || array[start] == '\t') {
  182. end--;
  183. } else {
  184. break;
  185. }
  186. }
  187. }
  188. for(int i = start; i < end; i++) {
  189. if(array[i] == '\n') {
  190. isSameLine = false;
  191. break;
  192. }
  193. }
  194. }
  195. super.characters(array, start, end - start);
  196. buffer.setLength(0);
  197. }
  198. }
  199. public void setDocumentLocator(Locator locator) {
  200. }
  201. public void startCDATA() throws SAXException {
  202. isLastText = true;
  203. flush();
  204. }
  205. public void notationDecl(String name, String publicId, String systemId) throws SAXException {
  206. }
  207. public void setSystemId(String systemID) {
  208. }
  209. public void startDocument() throws SAXException {
  210. }
  211. public void endCDATA() throws SAXException {
  212. }
  213. public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
  214. }
  215. public String getSystemId() {
  216. return null;
  217. }
  218. public void endDocument() throws SAXException {
  219. }
  220. public void startPrefixMapping(String prefix, String uri) throws SAXException {
  221. }
  222. public void endPrefixMapping(String prefix) throws SAXException {
  223. }
  224. public void skippedEntity(String name) throws SAXException {
  225. }
  226. public void setResult(Result result) throws IllegalArgumentException {
  227. }
  228. public void ignorableWhitespace(char[] chars, int i, int i1) throws SAXException {
  229. }
  230. public void endDTD() throws SAXException {
  231. }
  232. public void attributeDecl(String s, String s1, String s2, String s3, String s4) throws SAXException {
  233. }
  234. public void endEntity(String s) throws SAXException {
  235. }
  236. public void elementDecl(String s, String s1) throws SAXException {
  237. }
  238. public void startDTD(String s, String s1, String s2) throws SAXException {
  239. }
  240. public void externalEntityDecl(String s, String s1, String s2) throws SAXException {
  241. }
  242. public void startEntity(String s) throws SAXException {
  243. }
  244. public void internalEntityDecl(String s, String s1) throws SAXException {
  245. }
  246. }