/plugins/XSLT/tags/xslt-0_5/xslt/XMLFragmentsString.java

#
Java | 236 lines | 146 code | 49 blank | 41 comment | 44 complexity | c372777f0786456dcddd3e6b7b26c809 MD5 | raw file

✨ Summary
  1. /*
  2. * XMLFragmentsString.java - Represents a sequence of XML fragments as a string
  3. *
  4. * Copyright (c) 2002 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. package xslt;
  21. import org.gjt.sp.jedit.jEdit;
  22. import org.w3c.dom.NamedNodeMap;
  23. import org.w3c.dom.Node;
  24. import org.w3c.dom.NodeList;
  25. import java.text.MessageFormat;
  26. /**
  27. * Represents a sequence of XML fragments as a string.
  28. *
  29. * @author Robert McKinnon
  30. */
  31. public class XMLFragmentsString {
  32. private static final int NO_INDENT = Integer.MIN_VALUE;
  33. private static final String NL = System.getProperty("line.separator");
  34. /** Maximum number of characters in the XML fragments result string */
  35. private static final Integer MAX_CHARS_IN_FRAGMENTS_STRING = new Integer(1000000);
  36. private final StringBuffer buffer = new StringBuffer("");
  37. /** Holds an array of the start position of each XML fragment in the fragments String */
  38. private int[] fragmentPositions;
  39. /**
  40. * Constructs string of XML fragments representing the nodes in the node list.
  41. * @param nodelist containing nodes to be represented as XML fragments.
  42. * @throws IllegalStateException if the generated string becomes too large.
  43. */
  44. public XMLFragmentsString(NodeList nodelist) throws IllegalArgumentException {
  45. int nodeCount = nodelist.getLength();
  46. this.fragmentPositions = new int[nodeCount];
  47. for(int i = 0; i < nodeCount; i++) {
  48. Node node = nodelist.item(i);
  49. this.fragmentPositions[i] = buffer.length();
  50. appendNode(node, 0, false);
  51. if(buffer.length() > MAX_CHARS_IN_FRAGMENTS_STRING.intValue()) {
  52. String errorMessage = jEdit.getProperty("xpath.result.message.large-xml-fragment");
  53. String msg = MessageFormat.format(errorMessage, new Object[]{MAX_CHARS_IN_FRAGMENTS_STRING});
  54. throw new IllegalStateException(msg);
  55. }
  56. }
  57. }
  58. /**
  59. * Returns string of XML fragments representing the sequence of nodes in a node set.
  60. */
  61. public String getString() {
  62. return buffer.toString();
  63. }
  64. /**
  65. * Returns the position in the string of fragment at the given index, or
  66. * if the given index is higher than the largest fragment index, returns the length of the string.
  67. *
  68. * @param index index of the fragment
  69. * @return fragment position in string, or length of string if index is too high
  70. */
  71. public int getFragmentPosition(int index) {
  72. if(index >= this.fragmentPositions.length) {
  73. return buffer.length();
  74. } else {
  75. return this.fragmentPositions[index];
  76. }
  77. }
  78. public int getFragmentCount() {
  79. return this.fragmentPositions.length;
  80. }
  81. private void appendNode(Node node, int indentLevel, boolean insideElement) {
  82. if(node != null) {
  83. short type = node.getNodeType();
  84. if(type == Node.ELEMENT_NODE) {
  85. appendElementNode(node, indentLevel);
  86. } else if(type == Node.TEXT_NODE) {
  87. appendTextNode(node, insideElement);
  88. } else if(type == Node.ATTRIBUTE_NODE) {
  89. appendAttributeNode(node);
  90. } else if(type == Node.DOCUMENT_NODE) {
  91. appendChildNodes(node.getChildNodes(), 0, -1);
  92. } else if(type == Node.COMMENT_NODE) {
  93. appendCommentNode(node, indentLevel);
  94. } else if(type == Node.PROCESSING_INSTRUCTION_NODE) {
  95. appendProcessingInstructionNode(node);
  96. } else {
  97. appendNode(node.getNextSibling(), indentLevel, true);
  98. }
  99. }
  100. }
  101. private void appendProcessingInstructionNode(Node node) {
  102. buffer.append("<?");
  103. buffer.append(node.getNodeName());
  104. buffer.append(" ");
  105. buffer.append(node.getNodeValue());
  106. buffer.append("?>");
  107. buffer.append(NL);
  108. }
  109. private void appendCommentNode(Node node, int indentLevel) {
  110. appendIndent(indentLevel);
  111. buffer.append("<!--");
  112. buffer.append(node.getNodeValue());
  113. buffer.append("-->");
  114. buffer.append(NL);
  115. }
  116. private void appendTextNode(Node node, boolean insideElement) {
  117. String value = node.getNodeValue();
  118. String trimmedValue = value.trim();
  119. if(trimmedValue.length() > 0 || !insideElement) {
  120. buffer.append(value);
  121. }
  122. if(!insideElement) {
  123. buffer.append(NL);
  124. }
  125. }
  126. private void appendElementNode(Node node, int indentLevel) {
  127. if(indentLevel != NO_INDENT) {
  128. appendIndent(indentLevel);
  129. }
  130. buffer.append('<');
  131. buffer.append(node.getNodeName());
  132. appendAttributes(node.getAttributes());
  133. NodeList nodes = node.getChildNodes();
  134. if(nodes.getLength() > 0) {
  135. buffer.append('>');
  136. Node firstNode = nodes.item(0);
  137. if(firstNode.getNodeType() == Node.TEXT_NODE && firstNode.getNodeValue().trim().length() > 0) {
  138. appendTextNode(nodes.item(0), true);
  139. appendChildNodes(nodes, 1, NO_INDENT);
  140. } else {
  141. buffer.append(NL);
  142. appendChildNodes(nodes, 0, indentLevel);
  143. appendIndent(indentLevel);
  144. }
  145. buffer.append("</");
  146. buffer.append(node.getNodeName());
  147. buffer.append('>');
  148. if(indentLevel != NO_INDENT) {
  149. buffer.append(NL);
  150. }
  151. } else {
  152. buffer.append("/>");
  153. if(indentLevel != NO_INDENT) {
  154. buffer.append(NL);
  155. }
  156. }
  157. }
  158. private void appendIndent(int indentLevel) {
  159. for(int i = 0; i < indentLevel; i++) {
  160. buffer.append(" ");
  161. }
  162. }
  163. private void appendAttribute(Node node) {
  164. buffer.append(node.getNodeName());
  165. buffer.append("=\"");
  166. buffer.append(node.getNodeValue());
  167. buffer.append('\"');
  168. }
  169. private void appendAttributes(NamedNodeMap attributes) {
  170. for(int i = 0; i < attributes.getLength(); i++) {
  171. buffer.append(' ');
  172. appendAttribute(attributes.item(i));
  173. }
  174. }
  175. private void appendAttributeNode(Node node) {
  176. appendAttribute(node);
  177. buffer.append(NL);
  178. }
  179. private void appendChildNodes(NodeList nodes, int startIndex, int indentLevel) {
  180. if(indentLevel != NO_INDENT) {
  181. indentLevel++;
  182. }
  183. for(int i = startIndex; i < nodes.getLength(); i++) {
  184. appendNode(nodes.item(i), indentLevel, true);
  185. }
  186. }
  187. }