fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * The contents of this file are subject to the terms
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * of the Common Development and Distribution License
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * (the License). You may not use this file except in
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * compliance with the License.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * You can obtain a copy of the License at
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * https://opensso.dev.java.net/public/CDDLv1.0.html or
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * See the License for the specific language governing
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * permission and limitations under the License.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * When distributing Covered Code, include this CDDL
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Header Notice in each file and include the License file
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * If applicable, add the following below the CDDL Header,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * with the fields enclosed by brackets [] replaced by
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * your own identifying information:
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * "Portions Copyrighted [year] [name of copyright owner]"
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * $Id: XMLDocument.java,v 1.3 2008/06/25 05:51:31 qcheng Exp $
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Represents a simple XML document in memory that may be edited and stored.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * This implementation relies exlusively on the syntactic correctness of the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * underlying document such as balancing of quotes and delimiters etc. If an
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * XML document meets these requirements, it can be used to instantiate this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * class and can then be edited using the public methods available in this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * class as well as in <code>XMLElement</code> class.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * The in-memroy XML representation does not include any meta information such
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * as <code>DOCTYPE</code> tags, processing instructions, or any commets. Such
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * tags are filtered out before the final in-memory representation of the XML
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document is constructed. However, when this document is saved, these meta
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * information tags are re-inserted in the appropriate places so as to preserve
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the original format of the document in all respects possible. Even white
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * spaces are preserved as far as possible.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * This implementation uses an adhoc scanner/parser and does not rely on any
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * third party libraries.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Majorpublic class XMLDocument implements IXMLUtilsConstants {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Creates an instance of XMLDocument using the specified <code>File</code>
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * object. No checking is done to ensure the availablity and readability of
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the file passed in as the argument. It is expected that the caller has
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * completed such checks and taken the necessary backups before creating
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * this instance.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param file
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * representing the XML document on file system.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in case an error occurse during the parsing of this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public XMLDocument(File file) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the root element for the given XML document. This element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * represents the entire XML document in memory and can be used to traverse
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * and edit various portions of the document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return the root element of the XML tree
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * A factory method used for the creation of new XML elements that can be
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added to this XML document at a later stage. When this method is called,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * a new <code>XMLElement</code> object is returned to the caller.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * However, this newly created element is still not attached to the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document anywhere and it is the responsiblity of the caller to attach it
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in the appropriate location.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param name
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the name of the new element to be created
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return the newly created element that can be added to the document
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in case the creation of the new element fails due to any
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public XMLElement newElement(String name) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * A factory method used for the creation of new XML elements that can be
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added to this XML document at a later stage. When this method is called,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * a new <code>XMLElement</code> object is returned to the caller.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * However, this newly created element is still not attached to the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document anywhere and it is the responsiblity of the caller to attach it
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in the appropriate location. Further, the element returned from this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * method is a collapsed element that is contained within a single bounded
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param name
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the name of the new element to be created
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return the newly created element that can be added to the document
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in case the creation of the new element fails due to any
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public XMLElement newCollapsedElement(String name) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * A factory method used for the creation of new XML elements that can be
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added to this XML document at a later stage. When this method is called,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * a new <code>XMLElement</code> object is returned to the caller.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * However, this newly created element is still not attached to the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document anywhere and it is the responsiblity of the caller to attach it
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in the appropriate location. Note that the supplied parameter
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * <code>xmlFragement</code> must be a valid well-formed xml element.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param xmlFragment
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the xml fragment which will be parsed into an element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return the newly created element that can be added to the document
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in case the creation of the new element fails due to any
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public XMLElement newElementFromXMLFragment(String xmlFragment)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major StringReader reader = new StringReader(xmlFragment);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList newTokens = getParser().parse(reader);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList filteredTokens = getFilteredTokens(newTokens);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList elements = getElements(filteredTokens);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to parse fragment into new element");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * A factory method used for the creation of new XML elements that can be
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added to this XML document at a later stage. When this method is called,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * a new <code>XMLElement</code> object is returned to the caller.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * However, this newly created element is still not attached to the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document anywhere and it is the responsiblity of the caller to attach it
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in the appropriate location.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param name
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the name of the new element to be created
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param value
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the value of the new element to be created
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return the newly created element that can be added to the document
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * in case the creation of the new element fails due to any
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public XMLElement newElement(String name, String value) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Stores the in-memory XML data to the file system.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * If the save operation did not succeed.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major writer = new BufferedWriter(new FileWriter(getDocumentFile()));
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major writer.write(((Token) rawTokens.get(i)).toString());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the number of spaces used for denoting one indent level. The
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * default indent level is set to <code>4</code> spaces. However, this can
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * be changed by calling this method anytime. This value comes into effect
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * only when any new element is added to the XML document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param spaces
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the number of spaces used to denote one level of indentation
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets a flag that is used by the document to indent value tokens when
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * adding child elements that have value. The default behavior is to indent
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * value tokens, but that can be changed to no indent by calling this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets a flag that is used by the document to indent value tokens when
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * adding child elements that have value. The default behavior is to indent
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * value tokens, but changed by calling <code>setNoValueIndent</code>
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * method, it can be reset back to its original state by calling this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the DOCTYPE string associated with the first DOCTYPE element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * present in this document. This method may return null if no DOCTYPE
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * token is already present in the document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * This methods provides a means to update the DOCTYPE element of the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document with a new value as supplied in the argument. This method will
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * throw an Exception if the given document does not contain a predefined
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * DOCTYPE element.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param newDoctypeString
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major public void updatedDoctypeString(String newDoctypeString) throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("FAILED to update DOCTYPE - no such element");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Adds a value token for the given element with the given value.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param value
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major void addValueTokenForElement(XMLElement element, String value)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major UnboundedToken valueToken = newValueToken(value);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major int startTokenIndex = element.getStartToken().getTokenIndex();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major int indentLevel = getIndentLevel(startTokenIndex);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major WhiteSpaceToken valueIndentToken = new WhiteSpaceToken(NEW_LINE
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major + getIndentStringForIndentLevel(indentLevel + 1));
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean added = false;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == startTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to add value token");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Adds the given XMLElement after the token whoes index matches the given
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * lastTokenIndex value. If the flag addAfterNewLine is true, a new line is
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added before the addition of the new element to this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param lastTokenIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param addAfterNewLine
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major void addXMLElementAfterTokenIndex(int lastTokenIndex, XMLElement element,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major addXMLElementAfterTokenIndex(lastTokenIndex, element, addAfterNewLine,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Adds the given XMLElement after the token whoes index matches the given
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * lastTokenIndex value. If the flag addAfterNewLine is true, a new line is
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * added before the addition of the new element to this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param lastTokenIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param addAfterNewLine
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param addOuterWhitespace
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major void addXMLElementAfterTokenIndex(int lastTokenIndex, XMLElement element,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean addAfterNewLine, boolean addOuterWhitespace)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major outerIndentString = getIndentStringForIndentLevel(getIndentLevel(
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major indentIncrementString = getIndentIncrementString();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean outerIndent = true;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList newTokens = element.getCollapsedTokens(outerIndentString,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major indentIncrementString, indentValueToken(), outerIndent);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean added = false;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == lastTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major WhiteSpaceToken wstoken = new WhiteSpaceToken(NEW_LINE);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major wstoken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Parent element not found: index "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Inserts the ending token for a given element which was initially added
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * or parsed into a collapsed element.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major void insertEndTokenForElement(XMLElement element) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major int startTokenIndex = element.getStartToken().getTokenIndex();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major int indentLevel = getIndentLevel(startTokenIndex);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major + getIndentStringForIndentLevel(indentLevel - 1);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major WhiteSpaceToken indentToken = new WhiteSpaceToken(indentString);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major indentToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major endToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean added = false;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == startTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to add end token for element: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Deletes the tokens from the token whoes index matches with startIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * upto the token whoes index matches with endIndex. Both these tokens are
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * included in the deletion as well.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param startIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param endIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major void deleteTokens(int startIndex, int endIndex) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean delete = false;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (delete == true) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to find last token: index " +
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (startIndex != endIndex && deleteCount < 2) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to delete tokens for range: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (startIndex == endIndex && deleteCount != 1) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Failed to delete token at index: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major + startIndex + ", delete count: " + deleteCount);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns an xml fragment that represents this element and any contained
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * child elements.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param beginTokenIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the index of the token where the string begins
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param endTokenIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the index of the token where the string ends
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return an xml fragment representing this element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major String toXMLFragment(int beginTokenIndex, int endTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major boolean inRange = false;
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == beginTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == endTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Factory method for creation a new value token with the given value.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param value
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private UnboundedToken newValueToken(String value) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major UnboundedToken valueToken = new UnboundedToken(value);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major valueToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Factory method for creating a new element with the given name, given
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * value and given attributes. The value and the attributes may be null.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param name
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param value
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param attributes
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private XMLElement newElement(String name, String value,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major return newElement(name, value, attributes, false);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Factory method for creating a new element with the given name, given
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * value and given attributes. The value and the attributes may be null. If
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * the boolean argument <code>collapsed</code> is set to true, the element
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * will have a single token for start and end marks. In this case if a
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * value is specified, it will result in the throwing of an exception to
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * indicate an invalid request.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param name
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param value
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param attributes
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param collapsed
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private XMLElement newElement(String name, String value,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList attributes, boolean collapsed) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major BoundedToken startToken = new BoundedToken(startTokenString);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major startToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (value != null && value.trim().length() > 0) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major "Cannot add a collapsed element with specified value");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major UnboundedToken valueToken = new UnboundedToken(value);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major valueToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major BoundedToken endToken = new BoundedToken("</" + name + ">");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major endToken.setTokenIndex(getParser().getNextTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (attributes != null && attributes.size() > 0) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major XMLElementAttribute attr = (XMLElementAttribute) it.next();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major result.updateAttribute(attr.getName(), attr.getValue());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the indent level for the given token.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param tokenIndex
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major return getRootElement().getIndentLevelForToken(tokenIndex, 0);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns a whitespace string which represents the indentation to be used
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * for a given indentLevel value.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param indentLevel
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private String getIndentStringForIndentLevel(int indentLevel) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major String indentIncrementString = getIndentIncrementString();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns a string with the number of spaces corresponding to the indent
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * depth set for this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Initializes the document with the given File object.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param file
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private void initDocument(File file) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major new InputStreamReader(new FileInputStream(file))));
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major setDoctypeTokenIndex(nextToken.getTokenIndex());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the DOCTYPE token associated with this document. May return
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * <code>null</code> if no such token is present.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextToken.getTokenIndex() == doctypeTokenIndex) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Creats an in-memory XML tree based on the parsed tokens in this
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major ArrayList elements = getElements(getFilteredTokens());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("More than one root elements encountered");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns a list of tokens that do not contain any whitespace tokens.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param rawTokens
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @return filtered tokens
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private ArrayList getFilteredTokens(ArrayList rawTokens) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Updates the tokens to create a set of filtered tokens that make up the
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * various XML elements etc for final creation of in-memory XML
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * representation.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major setFilteredTokens(getFilteredTokens(getRawTokens()));
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the attributes from the given attribute string.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param attributeString
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private ArrayList getAttributes(String attributeString) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the attributes from the given attribute strings of the starting
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * and the ending tokens of any element.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param attributeStringBegin
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param attributeStringEnd
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private ArrayList getAttributes(String attributeStringBegin,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major return getParser().parseAttributes(attributeString);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Walks through the filtered token set to create an in-memory
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * representation of the XML document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param tokenList
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @throws Exception
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private ArrayList getElements(ArrayList tokenList) throws Exception {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (tokenList != null && tokenList.size() > 0) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major Token firstToken = (Token) tokenList.get(count);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major String attributeString = token.getAttributeString();
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major Token secondToken = (Token) tokenList.get(count + 1);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major BoundedToken secondBoundedToken = (BoundedToken)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (element == null && tokenList.size() >= count + 3) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major Token midToken = (Token) tokenList.get(count + 1);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major Token thirdToken = (Token) tokenList.get(count + 2);
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Malformed token encountered: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (!thirdBoundedToken.getName().equals(elementName)) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Malformed token encountered: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major throw new Exception("Malformed token encountered: "
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major for (int i = count + 1; i < tokenList.size(); i++) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major if (nextBoundedToken.getName().equals(elementName))
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the raw tokens for this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the raw tokens for this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param rawTokens
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private void setRawTokens(ArrayList rawTokens) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the filtered tokens for this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param filteredTokens
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major private void setFilteredTokens(ArrayList filteredTokens) {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the filted tokens for this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the root element of this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param root
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the parser to be used with this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param parser
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the parser that is used with this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the file object which is the source of this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param file
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the file object that is the source of this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the preffered indentation depth of this document.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns true if the value token should be indented while adding new
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * elements to this document, false otherwise.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Sets the document type token index
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * @param index
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Returns the document type token index. May return <code>-1</code> if no
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * document type token was found.