📄 xmloutputter.java
字号:
/**
* This will print indents only if indent is not null or the empty string.
*
* @param out <code>Writer</code> to use
* @param level current indent level
*/
private void indent(Writer out, int level) throws IOException {
if (currentFormat.indent == null ||
currentFormat.indent.equals("")) {
return;
}
for (int i = 0; i < level; i++) {
out.write(currentFormat.indent);
}
}
// Returns the index of the first non-all-whitespace CDATA or Text,
// index = content.size() is returned if content contains
// all whitespace.
// @param start index to begin search (inclusive)
private int skipLeadingWhite(List content, int start) {
if (start < 0) {
start = 0;
}
int index = start;
int size = content.size();
if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
|| currentFormat.mode == Format.TextMode.NORMALIZE
|| currentFormat.mode == Format.TextMode.TRIM) {
while (index < size) {
if (!isAllWhitespace(content.get(index))) {
return index;
}
index++;
}
}
return index;
}
// Return the index + 1 of the last non-all-whitespace CDATA or
// Text node, index < 0 is returned
// if content contains all whitespace.
// @param start index to begin search (exclusive)
private int skipTrailingWhite(List content, int start) {
int size = content.size();
if (start > size) {
start = size;
}
int index = start;
if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
|| currentFormat.mode == Format.TextMode.NORMALIZE
|| currentFormat.mode == Format.TextMode.TRIM) {
while (index >= 0) {
if (!isAllWhitespace(content.get(index - 1)))
break;
--index;
}
}
return index;
}
// Return the next non-CDATA, non-Text, or non-EntityRef node,
// index = content.size() is returned if there is no more non-CDATA,
// non-Text, or non-EntiryRef nodes
// @param start index to begin search (inclusive)
private static int nextNonText(List content, int start) {
if (start < 0) {
start = 0;
}
int index = start;
int size = content.size();
while (index < size) {
Object node = content.get(index);
if (!((node instanceof Text) || (node instanceof EntityRef))) {
return index;
}
index++;
}
return size;
}
// Determine if a Object is all whitespace
private boolean isAllWhitespace(Object obj) {
String str = null;
if (obj instanceof String) {
str = (String) obj;
}
else if (obj instanceof Text) {
str = ((Text) obj).getText();
}
else if (obj instanceof EntityRef) {
return false;
}
else {
return false;
}
for (int i = 0; i < str.length(); i++) {
if (!Verifier.isXMLWhitespace(str.charAt(i)))
return false;
}
return true;
}
// Determine if a string starts with a XML whitespace.
private boolean startsWithWhite(String str) {
if ((str != null) &&
(str.length() > 0) &&
Verifier.isXMLWhitespace(str.charAt(0))) {
return true;
}
return false;
}
// Determine if a string ends with a XML whitespace.
private boolean endsWithWhite(String str) {
if ((str != null) &&
(str.length() > 0) &&
Verifier.isXMLWhitespace(str.charAt(str.length() - 1))) {
return true;
}
return false;
}
/**
* This will take the pre-defined entities in XML 1.0 and
* convert their character representation to the appropriate
* entity reference, suitable for XML attributes. It does not convert
* the single quote (') because it's not necessary as the outputter
* writes attributes surrounded by double-quotes.
*
* @param str <code>String</code> input to escape.
* @return <code>String</code> with escaped content.
*/
public String escapeAttributeEntities(String str) {
StringBuffer buffer;
char ch;
String entity;
EscapeStrategy strategy = currentFormat.escapeStrategy;
buffer = null;
for (int i = 0; i < str.length(); i++) {
ch = str.charAt(i);
switch(ch) {
case '<' :
entity = "<";
break;
case '>' :
entity = ">";
break;
/*
case '\'' :
entity = "'";
break;
*/
case '\"' :
entity = """;
break;
case '&' :
entity = "&";
break;
case '\r' :
entity = "
";
break;
case '\t' :
entity = "	";
break;
case '\n' :
entity = "
";
break;
default :
if (strategy.shouldEscape(ch)) {
entity = "&#x" + Integer.toHexString(ch) + ";";
}
else {
entity = null;
}
break;
}
if (buffer == null) {
if (entity != null) {
// An entity occurred, so we'll have to use StringBuffer
// (allocate room for it plus a few more entities).
buffer = new StringBuffer(str.length() + 20);
// Copy previous skipped characters and fall through
// to pickup current character
buffer.append(str.substring(0, i));
buffer.append(entity);
}
}
else {
if (entity == null) {
buffer.append(ch);
}
else {
buffer.append(entity);
}
}
}
// If there were any entities, return the escaped characters
// that we put in the StringBuffer. Otherwise, just return
// the unmodified input string.
return (buffer == null) ? str : buffer.toString();
}
/**
* This will take the three pre-defined entities in XML 1.0
* (used specifically in XML elements) and convert their character
* representation to the appropriate entity reference, suitable for
* XML element content.
*
* @param str <code>String</code> input to escape.
* @return <code>String</code> with escaped content.
*/
public String escapeElementEntities(String str) {
if (escapeOutput == false) return str;
StringBuffer buffer;
char ch;
String entity;
EscapeStrategy strategy = currentFormat.escapeStrategy;
buffer = null;
for (int i = 0; i < str.length(); i++) {
ch = str.charAt(i);
switch(ch) {
case '<' :
entity = "<";
break;
case '>' :
entity = ">";
break;
case '&' :
entity = "&";
break;
case '\r' :
entity = "
";
break;
case '\n' :
entity = currentFormat.lineSeparator;
break;
default :
if (strategy.shouldEscape(ch)) {
entity = "&#x" + Integer.toHexString(ch) + ";";
}
else {
entity = null;
}
break;
}
if (buffer == null) {
if (entity != null) {
// An entity occurred, so we'll have to use StringBuffer
// (allocate room for it plus a few more entities).
buffer = new StringBuffer(str.length() + 20);
// Copy previous skipped characters and fall through
// to pickup current character
buffer.append(str.substring(0, i));
buffer.append(entity);
}
}
else {
if (entity == null) {
buffer.append(ch);
}
else {
buffer.append(entity);
}
}
}
// If there were any entities, return the escaped characters
// that we put in the StringBuffer. Otherwise, just return
// the unmodified input string.
return (buffer == null) ? str : buffer.toString();
}
/**
* Returns a copy of this XMLOutputter.
*/
public Object clone() {
// Implementation notes: Since all state of an XMLOutputter is
// embodied in simple private instance variables, Object.clone
// can be used. Note that since Object.clone is totally
// broken, we must catch an exception that will never be
// thrown.
try {
return super.clone();
}
catch (java.lang.CloneNotSupportedException e) {
// even though this should never ever happen, it's still
// possible to fool Java into throwing a
// CloneNotSupportedException. If that happens, we
// shouldn't swallow it.
throw new RuntimeException(e.toString());
}
}
/**
* Return a string listing of the settings for this
* XMLOutputter instance.
*
* @return a string listing the settings for this XMLOutputter instance
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < userFormat.lineSeparator.length(); i++) {
char ch = userFormat.lineSeparator.charAt(i);
switch (ch) {
case '\r': buffer.append("\\r");
break;
case '\n': buffer.append("\\n");
break;
case '\t': buffer.append("\\t");
break;
default: buffer.append("[" + ((int)ch) + "]");
break;
}
}
return (
"XMLOutputter[omitDeclaration = " + userFormat.omitDeclaration + ", " +
"encoding = " + userFormat.encoding + ", " +
"omitEncoding = " + userFormat.omitEncoding + ", " +
"indent = '" + userFormat.indent + "'" + ", " +
"expandEmptyElements = " + userFormat.expandEmptyElements + ", " +
"lineSeparator = '" + buffer.toString() + "', " +
"textMode = " + userFormat.mode + "]"
);
}
/**
* Factory for making new NamespaceStack objects. The NamespaceStack
* created is actually an inner class extending the package protected
* NamespaceStack, as a way to make NamespaceStack "friendly" toward
* subclassers.
*/
private NamespaceStack createNamespaceStack() {
// actually returns a XMLOutputter.NamespaceStack (see below)
return new NamespaceStack();
}
/**
* Our own null subclass of NamespaceStack. This plays a little
* trick with Java access protection. We want subclasses of
* XMLOutputter to be able to override protected methods that
* declare a NamespaceStack parameter, but we don't want to
* declare the parent NamespaceStack class as public.
*/
protected class NamespaceStack
extends org.jdom.output.NamespaceStack
{
}
// Support method to print a name without using elt.getQualifiedName()
// and thus avoiding a StringBuffer creation and memory churn
private void printQualifiedName(Writer out, Element e) throws IOException {
if (e.getNamespace().getPrefix().length() == 0) {
out.write(e.getName());
}
else {
out.write(e.getNamespace().getPrefix());
out.write(':');
out.write(e.getName());
}
}
// Support method to print a name without using att.getQualifiedName()
// and thus avoiding a StringBuffer creation and memory churn
private void printQualifiedName(Writer out, Attribute a) throws IOException {
String prefix = a.getNamespace().getPrefix();
if ((prefix != null) && (!prefix.equals(""))) {
out.write(prefix);
out.write(':');
out.write(a.getName());
}
else {
out.write(a.getName());
}
}
// * * * * * * * * * * Deprecated methods * * * * * * * * * *
/* The methods below here are deprecations of protected methods. We
* don't usually deprecate protected methods, so they're commented out.
* They're left here in case this mass deprecation causes people trouble.
* Since we're getting close to 1.0 it's actually better for people to
* raise issues early though.
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -