📄 litexmlelement.java
字号:
String result = building.toString().trim();
if( 0 == result.length() )
return null;
return result;
}
/**
* Write the contents of this element and optionally its children. The
* writing is done to a provided java.io.Writer. The writing can optionally
* be indented
*
* @param into The java.io.Writer that the output will be sent to.
* @param indent the number of tabs which will be inserted before each
* line.
* @param recurse if true then also print the children of this element.
*
**/
protected void printNice( Writer into, int indent, boolean recurse ) {
if( null != uninserted )
throw new IllegalStateException( "This element has not been added." );
try {
// do indent
for( int eachTab = 0; eachTab < indent; eachTab++ )
into.write( "\t" );
// print node name
into.write( doc.docContent.substring(loc.startTag.start, loc.startTag.end + 1) + "\n" );
String itsValue = getTextValue( true );
// print node value
if ( null != itsValue ) {
// do indent
for( int eachTab = 0; eachTab < indent + 1; eachTab++ )
into.write( "\t" );
into.write( itsValue + "\n" );
}
// recurse as needed
if ( recurse )
for( Enumeration childrens = getChildren(); childrens.hasMoreElements(); )
((LiteXMLElement)childrens.nextElement()).printNice( into, indent + 1, recurse );
// do indent
for( int eachTab = 0; eachTab < indent; eachTab++ )
into.write( "\t" );
// print node name
into.write( doc.docContent.substring(loc.endTag.start, loc.endTag.end + 1) + "\n" );
}
catch( IOException ignored ) {
// we ignore any io errors
}
}
/**
* Given a source string, an optional tag and a range with in the source
* find either the tag specified or the next tag.
*
* The search consists of 4 phases :
* 0. If no tag was specified, determine if a tag can be found and
* learn its name.
* 1. Search for the start of the named tag.
* 2. Search for the end tag. Each time we think we have found a tag
* which might be the end tag we make sure it is not the end tag
* of another element with the same name as our tag.
* 3. Calculate the position of the body of the tag given the locations
* of the start and end.
*
* @param source the string to search
* @param tag the tag to search for in the source string. If this tag is
* empty or null then we will search for the next tag.
* @param range describes the range of character locations in the source
* string to which the search will be limited.
* @return tagRange containing the ranges of the found tag.
*/
protected tagRange getTagRanges( final String source, String tag, final charRange range ) {
// FIXME bondolo@jxta.org 20010327 Does not handle XML comments. ie. <!-- -->
if( null != uninserted )
throw new IllegalStateException( "This element has not been added to the document." );
tagRange result = new LiteXMLElement.tagRange();
int start = range.start;
int end = source.length() - 1;
int current;
boolean foundStartTag = false;
boolean foundEndTag = false;
boolean emptyTag = ( (null == tag) || ("".equals(tag)) );
//System.err.println( "Tag : " + tag + " Start : " + start + " End: " + end + " a bit : " + source.substring( start, start + 11 ) );
// check for bogosity
if( (-1 == start) || (start >= end) )
return result;
// adjust end of range
if( (-1 != range.end) && (end > range.end) )
end = range.end;
// check for empty tag and assign empty string
if( null == tag )
tag = "";
current = start;
// Begin Phase 0 : Search for any tag.
if( emptyTag ) {
int foundTagText = source.indexOf( '<', current );
int afterTagText;
// was it not found? if not then quit
if( -1 == foundTagText )
return result;
// this part is about setting the tag if necessary
foundTagText++;
afterTagText = foundTagText;
while( afterTagText <= end ) {
if( -1 == " \t\n\r/>".indexOf( source.charAt(afterTagText) ) ) {
afterTagText++;
continue;
}
tag = source.substring( foundTagText, afterTagText );
emptyTag = ( (null == tag) || ("".equals(tag)) );
break;
}
// it better not be still empty
if( emptyTag )
return result;
}
// Begin Phase 1: Search for the Start Tag
//start looking for the start tag
while( !foundStartTag && (current < end) ) {
int foundTagText = source.indexOf( tag, current + 1); // first loc is one past current location
int foundTagTerminator;
int foundNextTagStart;
int afterTagText = foundTagText + tag.length();
// was it not found
if( ( -1 == foundTagText ) || (afterTagText > end) )
return result;
// check to see if it is the start tag
if( ('<' != source.charAt( foundTagText - 1)) || // it has the open tag delimiter before it
( -1 == " \t\n\r/>".indexOf( source.charAt(afterTagText) ) ) ) { // is immediately followed by a delimiter
current = afterTagText;
continue;
}
foundTagTerminator = source.indexOf( '>', afterTagText );
foundNextTagStart = source.indexOf( '<', afterTagText + 1 );
if( (-1 == foundTagTerminator) || // the tag has no terminator
(foundTagTerminator > end) || // it is past the valid range
( (-1 != foundNextTagStart) && // there is another tag start
(foundNextTagStart < foundTagTerminator) ) ) { // and it is before the terminator we found. very bad
current = afterTagText;
continue;
}
foundStartTag = true;
result.startTag.start = foundTagText - 1;
result.startTag.end = foundTagTerminator;
}
if( !foundStartTag )
return result;
// is this an empty element declaration?
if( '/' == source.charAt( result.startTag.end - 1 ) ) {
result.endTag = result.startTag; // end is the start and there is no body
return result;
}
current = result.startTag.end + 1;
tagRange subElement = null;
// if current is past the end then our end tag is not found.
if( current >= end )
return result;
// Begin Phase 2 : Search for the end tag
String endTag = "</" + tag + ">";
while( !foundEndTag && (current < end) ) {
int foundTagText = source.indexOf( endTag, current );
// was it not found or not in bounds?
if( (-1 == foundTagText) || ((foundTagText + endTag.length() - 1) > end) )
break; // it was not found
// We recurse here in order to exclude the end tags of any sub elements with the same name
subElement = getTagRanges( source, tag, new charRange( current, foundTagText - 1 ) );
// if there was a sub-tag with the same name, skip past it
if( subElement.startTag.isValid() ) {
/* System.err.println( "found a sub-tag with our name (" + tag +
") at : (" + subElement.startTag.start + "," + subElement.endTag.end + ") in range (" +
current + "," + (foundTagText - 1) + ")" ); */
current = foundTagText + endTag.length();
continue;
}
foundEndTag = true;
result.endTag.start = foundTagText;
result.endTag.end = foundTagText + endTag.length() - 1;
}
// Begin Phase 3 : Calculate the location of the body.
result.body.start = result.startTag.end + 1;
if( foundEndTag ) {
result.body.end = result.endTag.start - 1;
}
else {
result.body.end = end;
}
return result;
}
/**
* Parse a charRange and add any tags found as content as children of a
* specified element. This process is repeated recursivly.
*
* @param scanRange the range to be parsed for sub-tags
* @param addTo the element to add any discovered children to.
*
*/
protected void addChildTags( final charRange scanRange, LiteXMLElement addTo ) {
if( null != uninserted )
throw new IllegalStateException( "This element has not been added." );
int current = scanRange.start;
do {
// scan for any tag.
tagRange aSubtag = getTagRanges( doc.docContent, null, new charRange( current, scanRange.end ) );
// did we find one?
if( aSubtag.isValid() ) {
LiteXMLElement newChild = (LiteXMLElement) doc.createElement( aSubtag );
addTo.appendChild(newChild);
addChildTags( aSubtag.body, newChild ); // recurse into the new tag
// all done this tag, move on
current = aSubtag.endTag.end + 1;
}
else
current = -1; // all done!
}
while( (-1 != current) && (current < scanRange.end) );
if( !loc.isValid() )
throw new IllegalStateException( "Document is damaged" );
}
/**
* For this element and all its children adjust the location of its ranges
* by the amount specified.
*
* @param beginningAt adjust all locations which are at or past this
* location.
* @param by amount to adjust all matching locations.
**/
protected void adjustLocations( final int beginningAt, final int by ) {
if( null != uninserted )
throw new IllegalStateException( "This element has not been added." );
if( (loc.startTag.end >= beginningAt) ||
((loc.startTag.start >= beginningAt) && ( (loc.startTag.end + 1) == loc.startTag.start)) )
loc.startTag.end += by;
if( loc.startTag.start >= beginningAt )
loc.startTag.start += by;
if( (loc.body.end >= beginningAt) ||
((loc.body.start >= beginningAt) && ( (loc.body.end + 1) == loc.body.start)) )
loc.body.end += by;
if( loc.body.start >= beginningAt )
loc.body.start += by;
if( (loc.endTag.end >= beginningAt) ||
((loc.endTag.start >= beginningAt) && ( (loc.endTag.end + 1) == loc.endTag.start)) )
loc.endTag.end += by;
if( loc.endTag.start >= beginningAt )
loc.endTag.start += by;
for( Enumeration eachChild = getChildren(); eachChild.hasMoreElements(); ) {
LiteXMLElement aChild = (LiteXMLElement) eachChild.nextElement();
aChild.adjustLocations( beginningAt, by );
}
if( !loc.isValid() )
throw new IllegalStateException( "Document is damaged" );
}
/**
* Given a StringBuffer find all occurances of escaped characters which
* must be decoded and convert them back to their non-escaped equivalents.
*
* @param target The stringbuffer which will be decoded.
* @return The decoded version of the stringbuffer.
*
**/
protected StringBuffer decodeEscaped( StringBuffer target ) {
int current = 0;
StringBuffer result = new StringBuffer();
while( current < target.length() ) {
// FIXME bondolo@jxta.org 20010422 Should process xml comments out here.
if( '&' != target.charAt( current ) ) {
result.append( target.charAt( current ) );
current++;
continue;
}
int terminusAt = current + 1;
while( (terminusAt < target.length()) && // dont go past end
((terminusAt - current) < 6 ) && // only look 6 chars away.
(';' != target.charAt(terminusAt)) ) // must be a ;
terminusAt++;
if( (terminusAt >= target.length()) || (';' != target.charAt(terminusAt)) ) {
// if we get here then we didnt find the terminal we needed
// so we just leave ampersand as it was, the document is
// ill-formed but why make things worse?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -