XMLFormatter.jsee
- /*
- * An Simple XML formatter that will format the user selected - valid xml.
- * It does not check structure as it only provides formatting capabilities and not parsing capabilities.
- * If invalid xml is passed to the formatter then the provided resulting stucture may be wrong.
- * 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.
- *
- * If you wish the text node to be displayed as below, please set the textOneLiner variable to true. e.g var textOneLiner = true;
- *
- *
some text - *
- * Otherwise if the value is false, then the text will be displayed as below, e.g. var textOneLiner = false;
- *
- *
- * some text
- *
- *
- * Conditions of use:-
- *
- * This formatter shall not be sold for profit or gain but may be used freely.
- * Sections of source code may be take from this document but the authours details must be provided with it.
- * If you feel that the code needs changing please contact me at the provided email address below,
- * as improvements would be greatly appreciated.
- *
- * @authour Andrew Peter Powell
- * @date 01/01/2008
- * @version 1.2
- * @email andrew@programmer.orangehome.co.uk
- * Copyright 2008
- */
-
- var tabSpaces = "";
- var tabs = "";
-
- var textOneLiner = true;
-
- /*
- * Main entry point that is fired when the macro is run
- * Prompts the user for the number of spaces to use for indentations
- */
- function formatDocument() {
-
- // var useTabs = confirm("Would you like to use tabs to indent?");
- //
- // var textualSeperator = "spaces";
- // var indentCharacter = " ";
- // if(useTabs == true) {
- // indentCharacter = "\t";
- // textualSeperator = "tabs"
- // }
- //
- // var val = prompt("Please enter the number of " + textualSeperator + " to indent", (indentCharacter == " " ? "4" : "1"));
-
- var indentCharacter = "\t";
-
- status = "Formatting Selected XML - Please Wait...";
-
- var spaces = 0;
- try {
- spaces = parseInt(1);
- // If is not a number then thrown an exception
- if(isNaN(spaces)) {
- throw val;
- }
- } catch(err) {
- alert("Unrecognised spacing \"" + err + "\" - Using default spacing of 4");
- spaces = 4;
- }
-
- // Create a string of the spacing to use
- for(var i = 0; i < spaces; i++) {
- tabSpaces += indentCharacter;
- }
-
- var documentArray;
- try {
- documentArray = getChunks();
- } catch(err) {
- alert(err);
- return;
- }
-
- var formattedArray = new Array();
-
- for(var j = 0; j < documentArray.length; j++) {
- // remove all new lines
- text = documentArray[j].replace(new RegExp( "\\n", "g" ), "");
- // old format /\r\n/gi;
- var storeArray = new Array();
-
- // Store each node in an array element
- process(text, storeArray);
-
- // format the lined array producing the formatted string that will be output.
- var formattedContent = format(storeArray);
-
- formattedArray.push(formattedContent);
- }
-
- // clear the selected text
- document.selection.Text = "";
-
- // loop through the formatted values and inject them into the page
- for(var k = 0; k < formattedArray.length; k++) {
- document.write(formattedArray[k]);
- }
-
- status = "Formatting Complete";
- }
-
- /* The number of characters give or take that will be stored in each chunk to be formatted */
- var chunkSize = 5000;
-
- /*
- * Store the whole selected document in an array
- */
- function getChunks() {
-
- // Get the whole selected text
- var selectedText = document.selection.Text;
-
- // Check that there is some xml tags selected
- if(selectedText.search("[<]{1}[^]*[>]{1}") == -1) {
- throw "Unable to find XML";
- }
-
- var documentArray = new Array();
-
- // Disect the string and then place in an array
- while(true) {
- if(selectedText.length > chunkSize) {
- // Find the next tag so that we may cut of the chunk at a valid point
- var endLength = selectedText.substring(chunkSize, selectedText.length).search("[<]{1}[^]*[>]{1}");
-
- // Get the text for this chunk
- var tempText = selectedText.substring(0, chunkSize + endLength);
-
- // Get last comment tag if any
- var startCommentTag = tempText.lastIndexOf("");
- var nextEndComment = 0;
- // we have cut the chunk of half way through a comment
- if(startCommentTag != -1 && startCommentTag > endCommentTag) {
- nextEndComment = selectedText.substring(chunkSize + endLength, selectedText.lenght).indexOf("-->");
- // Get the text for this chunk
- tempText = selectedText.substring(0, chunkSize + endLength + nextEndComment + 4);
- }
-
- // Add the raw text onto the array
- documentArray.push(tempText);
- // substring the String, so that it continue where the last chunk was taken from
- selectedText = selectedText.substring(chunkSize + endLength + (nextEndComment == 0 ? 0 : nextEndComment + 4), selectedText.length);
- } else {
- // Add the last bit onto the array
- documentArray.push(selectedText);
- break;
- }
- }
-
- return documentArray;
- }
-
- /*
- * Recursive method that processed the raw xml chunk with the new lines having been removes.
- */
- function process(theText, storeArray) {
- var commentStartTag = theText.indexOf("");
-
- var startTag = theText.indexOf("<");
- var endTag = theText.indexOf(">");
-
- // If a comment tag is used then find the end
- if(commentStartTag != -1 && commentStartTag <= startTag && commentEndTag > commentStartTag) {
- var subString = theText.substring(commentStartTag, commentEndTag + 4);
- if(commentStartTag > 0) {
- var text = theText.substring(0, commentStartTag);
- // Remove white space surrounding the text tha may exist before the start tag
- text = text.replace(/^\s+|\s+$/g,"");
- if(text != "") {
- // Add the text
- storeArray.push(text);
- }
- }
- // Add the node
- storeArray.push(subString);
- // Get the next section of the string
- var nextText = theText.substring(commentEndTag + 4, theText.length);
- // Recursive call to find the next tag
- process(nextText, storeArray);
- }
- // If we find a valid start and end position
- else if(endTag > startTag) {
- var subString = theText.substring(startTag, endTag + 1);
-
- // Add text if before start tag
- if(startTag > 0) {
- var text = theText.substring(0, startTag);
- // Remove white space surrounding the text tha may exist before the start tag
- text = text.replace(/^\s+|\s+$/g,"");
- if(text != "") {
- // Add the text
- storeArray.push(text);
- }
- }
-
- // Add the node
- storeArray.push(subString);
- // Get the next section of the string
- var nextText = theText.substring(endTag + 1, theText.length);
- // Recursive call to find the next tag
- process(nextText, storeArray);
- }
- // If we have hit the end and there is still text then add the final text
- else if(startTag == -1 && endTag == -1 && theText.length != 0) {
- var text = theText.replace(/^\s+|\s+$/g,"");
- if(text != "") {
- // Add the text
- storeArray.push(text);
- }
- process("", storeArray);
- }
- else {
- // We have hit the end so return
- return;
- }
-
- }
-
- /* A stack array that will hold the start tag node to help find the closing node and indentations */
- var stack = new Array();
-
- /*
- * An object that will hold the tag name without surrounding < >, and the current indentation use for that node
- */
- function tagNode(value, indent) {
- this.value = value;
- this.indent = indent;
- }
-
- /*
- * Get the name of the node
- */
- function tagNode.prototype.getValue() {
- return this.value;
- }
-
- /*
- * Get the indent for the node
- */
- function tagNode.prototype.getIndent() {
- return this.indent;
- }
-
- /**
- * Strip the string and just find the tag name
- * If the value does not have a tag syntax then it must be text, a comment or an xml defenition
- */
- function getTagName(value) {
- var startPos = value.indexOf("<");
- var endPos = value.indexOf(">");
- var oneLiner = value.indexOf("/>");
- var endTag = value.indexOf("");
- var xmlDefTag = value.indexOf(");
- var comment = value.indexOf("