• EmEditor文本编辑器添加宏,实现xml报文格式化显示


    XMLFormatter.jsee

    1. /*
    2. * An Simple XML formatter that will format the user selected - valid xml.
    3. * It does not check structure as it only provides formatting capabilities and not parsing capabilities.
    4. * If invalid xml is passed to the formatter then the provided resulting stucture may be wrong.
    5. * It has been tested on a 200,000 line xml document, which it can process in about 1 minute. For an 9000 line xml stucture, it can process it within 4 seconds.
    6. *
    7. * If you wish the text node to be displayed as below, please set the textOneLiner variable to true. e.g var textOneLiner = true;
    8. *
    9. * some text
    10. *
    11. * Otherwise if the value is false, then the text will be displayed as below, e.g. var textOneLiner = false;
    12. *
    13. *
    14. * some text
    15. *
    16. *
    17. * Conditions of use:-
    18. *
    19. * This formatter shall not be sold for profit or gain but may be used freely.
    20. * Sections of source code may be take from this document but the authours details must be provided with it.
    21. * If you feel that the code needs changing please contact me at the provided email address below,
    22. * as improvements would be greatly appreciated.
    23. *
    24. * @authour Andrew Peter Powell
    25. * @date 01/01/2008
    26. * @version 1.2
    27. * @email andrew@programmer.orangehome.co.uk
    28. * Copyright 2008
    29. */
    30. var tabSpaces = "";
    31. var tabs = "";
    32. var textOneLiner = true;
    33. /*
    34. * Main entry point that is fired when the macro is run
    35. * Prompts the user for the number of spaces to use for indentations
    36. */
    37. function formatDocument() {
    38. // var useTabs = confirm("Would you like to use tabs to indent?");
    39. //
    40. // var textualSeperator = "spaces";
    41. // var indentCharacter = " ";
    42. // if(useTabs == true) {
    43. // indentCharacter = "\t";
    44. // textualSeperator = "tabs"
    45. // }
    46. //
    47. // var val = prompt("Please enter the number of " + textualSeperator + " to indent", (indentCharacter == " " ? "4" : "1"));
    48. var indentCharacter = "\t";
    49. status = "Formatting Selected XML - Please Wait...";
    50. var spaces = 0;
    51. try {
    52. spaces = parseInt(1);
    53. // If is not a number then thrown an exception
    54. if(isNaN(spaces)) {
    55. throw val;
    56. }
    57. } catch(err) {
    58. alert("Unrecognised spacing \"" + err + "\" - Using default spacing of 4");
    59. spaces = 4;
    60. }
    61. // Create a string of the spacing to use
    62. for(var i = 0; i < spaces; i++) {
    63. tabSpaces += indentCharacter;
    64. }
    65. var documentArray;
    66. try {
    67. documentArray = getChunks();
    68. } catch(err) {
    69. alert(err);
    70. return;
    71. }
    72. var formattedArray = new Array();
    73. for(var j = 0; j < documentArray.length; j++) {
    74. // remove all new lines
    75. text = documentArray[j].replace(new RegExp( "\\n", "g" ), "");
    76. // old format /\r\n/gi;
    77. var storeArray = new Array();
    78. // Store each node in an array element
    79. process(text, storeArray);
    80. // format the lined array producing the formatted string that will be output.
    81. var formattedContent = format(storeArray);
    82. formattedArray.push(formattedContent);
    83. }
    84. // clear the selected text
    85. document.selection.Text = "";
    86. // loop through the formatted values and inject them into the page
    87. for(var k = 0; k < formattedArray.length; k++) {
    88. document.write(formattedArray[k]);
    89. }
    90. status = "Formatting Complete";
    91. }
    92. /* The number of characters give or take that will be stored in each chunk to be formatted */
    93. var chunkSize = 5000;
    94. /*
    95. * Store the whole selected document in an array
    96. */
    97. function getChunks() {
    98. // Get the whole selected text
    99. var selectedText = document.selection.Text;
    100. // Check that there is some xml tags selected
    101. if(selectedText.search("[<]{1}[^]*[>]{1}") == -1) {
    102. throw "Unable to find XML";
    103. }
    104. var documentArray = new Array();
    105. // Disect the string and then place in an array
    106. while(true) {
    107. if(selectedText.length > chunkSize) {
    108. // Find the next tag so that we may cut of the chunk at a valid point
    109. var endLength = selectedText.substring(chunkSize, selectedText.length).search("[<]{1}[^]*[>]{1}");
    110. // Get the text for this chunk
    111. var tempText = selectedText.substring(0, chunkSize + endLength);
    112. // Get last comment tag if any
    113. var startCommentTag = tempText.lastIndexOf("");
    114. var nextEndComment = 0;
    115. // we have cut the chunk of half way through a comment
    116. if(startCommentTag != -1 && startCommentTag > endCommentTag) {
    117. nextEndComment = selectedText.substring(chunkSize + endLength, selectedText.lenght).indexOf("-->");
    118. // Get the text for this chunk
    119. tempText = selectedText.substring(0, chunkSize + endLength + nextEndComment + 4);
    120. }
    121. // Add the raw text onto the array
    122. documentArray.push(tempText);
    123. // substring the String, so that it continue where the last chunk was taken from
    124. selectedText = selectedText.substring(chunkSize + endLength + (nextEndComment == 0 ? 0 : nextEndComment + 4), selectedText.length);
    125. } else {
    126. // Add the last bit onto the array
    127. documentArray.push(selectedText);
    128. break;
    129. }
    130. }
    131. return documentArray;
    132. }
    133. /*
    134. * Recursive method that processed the raw xml chunk with the new lines having been removes.
    135. */
    136. function process(theText, storeArray) {
    137. var commentStartTag = theText.indexOf("");
    138. var startTag = theText.indexOf("<");
    139. var endTag = theText.indexOf(">");
    140. // If a comment tag is used then find the end
    141. if(commentStartTag != -1 && commentStartTag <= startTag && commentEndTag > commentStartTag) {
    142. var subString = theText.substring(commentStartTag, commentEndTag + 4);
    143. if(commentStartTag > 0) {
    144. var text = theText.substring(0, commentStartTag);
    145. // Remove white space surrounding the text tha may exist before the start tag
    146. text = text.replace(/^\s+|\s+$/g,"");
    147. if(text != "") {
    148. // Add the text
    149. storeArray.push(text);
    150. }
    151. }
    152. // Add the node
    153. storeArray.push(subString);
    154. // Get the next section of the string
    155. var nextText = theText.substring(commentEndTag + 4, theText.length);
    156. // Recursive call to find the next tag
    157. process(nextText, storeArray);
    158. }
    159. // If we find a valid start and end position
    160. else if(endTag > startTag) {
    161. var subString = theText.substring(startTag, endTag + 1);
    162. // Add text if before start tag
    163. if(startTag > 0) {
    164. var text = theText.substring(0, startTag);
    165. // Remove white space surrounding the text tha may exist before the start tag
    166. text = text.replace(/^\s+|\s+$/g,"");
    167. if(text != "") {
    168. // Add the text
    169. storeArray.push(text);
    170. }
    171. }
    172. // Add the node
    173. storeArray.push(subString);
    174. // Get the next section of the string
    175. var nextText = theText.substring(endTag + 1, theText.length);
    176. // Recursive call to find the next tag
    177. process(nextText, storeArray);
    178. }
    179. // If we have hit the end and there is still text then add the final text
    180. else if(startTag == -1 && endTag == -1 && theText.length != 0) {
    181. var text = theText.replace(/^\s+|\s+$/g,"");
    182. if(text != "") {
    183. // Add the text
    184. storeArray.push(text);
    185. }
    186. process("", storeArray);
    187. }
    188. else {
    189. // We have hit the end so return
    190. return;
    191. }
    192. }
    193. /* A stack array that will hold the start tag node to help find the closing node and indentations */
    194. var stack = new Array();
    195. /*
    196. * An object that will hold the tag name without surrounding < >, and the current indentation use for that node
    197. */
    198. function tagNode(value, indent) {
    199. this.value = value;
    200. this.indent = indent;
    201. }
    202. /*
    203. * Get the name of the node
    204. */
    205. function tagNode.prototype.getValue() {
    206. return this.value;
    207. }
    208. /*
    209. * Get the indent for the node
    210. */
    211. function tagNode.prototype.getIndent() {
    212. return this.indent;
    213. }
    214. /**
    215. * Strip the string and just find the tag name
    216. * If the value does not have a tag syntax then it must be text, a comment or an xml defenition
    217. */
    218. function getTagName(value) {
    219. var startPos = value.indexOf("<");
    220. var endPos = value.indexOf(">");
    221. var oneLiner = value.indexOf("/>");
    222. var endTag = value.indexOf(");
    223. var xmlDefTag = value.indexOf(");