Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright 2012 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/*
* @author mchyzer
* $Id: XmlIndenter.java,v 1.1 2008-11-30 10:57:27 mchyzer Exp $
*/
package edu.internet2.middleware.grouperInstaller.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* indent xml, assumes the input is not yet indented. Also, this is only for
* testing or logging or documentation purposes, not production
*/
public class XmlIndenter {
/** chars to process */
private String xml;
/** current start tag */
private int startTagIndex;
/** current end tag */
private int endTagIndex;
/** current number of indents (times to is the indent */
private int currentNumberOfIndents;
/** current tag we are on */
private String currentTagName;
/** result */
private StringBuilder result;
/**
* get the result
* @return the result
*/
public String result() {
try {
this.indent();
} catch (RuntimeException re) {
throw new RuntimeException("Problem here: " + this, re);
}
if (this.xml == null) {
return null;
}
return GrouperInstallerUtils.trim(this.result.toString());
}
/**
* indent the string
*/
private void indent() {
if (this.xml == null) {
return;
}
this.result = new StringBuilder();
this.startTagIndex = -1;
this.endTagIndex = -1;
this.currentTagName = null;
this.currentNumberOfIndents = 0;
//heythere
//
//
// hey
//
// there
//
//
//
//
//
//
while(true) {
this.startTagIndex = findStartTagIndex();
if (this.startTagIndex == -1) {
//cant find anything else... make sure everything there
if (this.endTagIndex != this.xml.length()-1) {
this.result.append(this.xml, this.endTagIndex+1, this.xml.length());
}
break;
}
this.endTagIndex = findEndTagIndex();
//if XML or doctype, then just print with newline and continue
if (ignoreTag(this.xml, this.startTagIndex, this.endTagIndex)) {
//just return and indent
//lets put this tag on the queue
this.printNewlineIndent(this.startTagIndex, this.endTagIndex+1);
continue;
}
this.currentTagName = findTagName();
//if self closed, then carry on
if (selfClosedTag(this.xml, this.endTagIndex)) {
//just return and indent
//lets put this tag on the queue
this.printNewlineIndent(this.startTagIndex, this.endTagIndex+1);
} else if (closeTag(this.xml, this.startTagIndex)) {
//if end tag, then return and unindent
this.unindent();
this.currentNumberOfIndents--;
//lets put this tag on the queue
this.printNewlineIndent(this.startTagIndex, this.endTagIndex+1);
} else {
int nextTagStartIndex = findNextStartTagIndex(this.xml, this.endTagIndex+1);
int nextTagEndIndex = findNextEndTagIndex(this.xml, nextTagStartIndex+1);
String nextTagName = tagName(this.xml, nextTagStartIndex, nextTagEndIndex);
boolean isNextTagCloseTag = closeTag(this.xml, nextTagStartIndex);
if (!textTag(this.xml, this.endTagIndex, this.currentTagName, nextTagName, isNextTagCloseTag)) {
this.currentNumberOfIndents++;
this.printNewlineIndent(this.startTagIndex, this.endTagIndex+1);
} else {
//else this is a text tag, print from here to end of next tag, newline and indent
this.printNewlineIndent(this.startTagIndex, nextTagEndIndex+1);
//increment past the next one
this.startTagIndex = nextTagEndIndex;
this.endTagIndex = nextTagEndIndex;
}
}
}
}
/**
* see if we can ignore the tag, e.g. xml header or doctype
* @param theXml
* @param theStartTagIndex
* @param theEndTagIndex
* @return true if ignore
*/
static boolean ignoreTag(String theXml, int theStartTagIndex, int theEndTagIndex) {
char firstChar = theXml.charAt(theStartTagIndex+1);
if (firstChar == '?' || firstChar == '!') {
return true;
}
return false;
}
/**
* put a newline and indent
* @param start
* @param end
*/
private void printNewlineIndent(int start, int end) {
//lets put this tag on the queue
this.result.append(this.xml, start, end);
this.newlineIndent();
}
/**
* put a newline and indent
*/
private void newlineIndent() {
this.result.append("\n").append(GrouperInstallerUtils.repeat(" ", this.currentNumberOfIndents));
}
/**
* unindent a previous indent if it is there
*/
private void unindent() {
for (int i=0;i<2;i++) {
if (this.result.charAt(this.result.length()-1) == ' ') {
this.result.deleteCharAt(this.result.length()-1);
}
}
}
/**
* find the current tag name
* should support: < a />
* or < / b>
* @param xml
* @param startTagIndex
* @param endTagIndex (or -1 if none found)
* @return the current tag name
*/
static String tagName(String xml, int startTagIndex, int endTagIndex) {
endTagIndex = endTagIndex > startTagIndex ? endTagIndex : (xml.length()-1);
String tag = xml.substring(startTagIndex, endTagIndex+1);
Pattern tagPattern = Pattern.compile("^<[\\s/]*([a-zA-Z_\\-0-9:\\.]+).*$", Pattern.DOTALL);
Matcher matcher = tagPattern.matcher(tag);
if (!matcher.matches()) {
throw new RuntimeException("Cant match tag: '" + tag + "'");
}
//assume this matches...
String tagName = matcher.group(1);
return tagName;
}
/**
* after the last end tag, find the next start tag
* @return the next start tag
*/
private int findStartTagIndex() {
return findNextStartTagIndex(this.xml, this.endTagIndex+1);
}
/**
* after the last end tag, find the next start tag
* @return the next start tag
*/
private String findTagName() {
return tagName(this.xml, this.startTagIndex, this.endTagIndex);
}
/**
* after the last start tag, find the next end start tag
* @return the next start tag
*/
private int findEndTagIndex() {
return findNextEndTagIndex(this.xml, this.startTagIndex+1);
}
/**
* find the start tag from xml and a start from index
* @param xml
* @param startFrom
* @return the start tag index of -1 if not found another
*/
static int findNextStartTagIndex(String xml, int startFrom) {
int length = xml.length();
for (int i= startFrom; i') {
return i;
}
}
return -1;
}
/**
* find if the tag is closed on
* @param xml
* @param endTagIndex
* @return true if self closed
*/
static boolean selfClosedTag(String xml, int endTagIndex) {
for (int i=endTagIndex-1;i>=0;i--) {
char curChar = xml.charAt(i);
//ignore whitespace
if (Character.isWhitespace(curChar)) {
continue;
}
if (curChar == '/') {
return true;
}
return false;
}
//shouldnt really get here...
return false;
}
/**
* find if the tag is a close tag (e.g. </a>)
* @param xml
* @param startTagIndex
* @return true if self closed
*/
static boolean closeTag(String xml, int startTagIndex) {
for (int i=startTagIndex+1;i