📄 processinginstruction.java
字号:
/**
* This will set a pseudo attribute with the given name and value.
* If the PI data is not already in a pseudo-attribute format, this will
* replace the existing data.
*
* @param name <code>String</code> name of pair.
* @param value <code>String</code> value for pair.
* @return <code>ProcessingInstruction</code> this PI modified.
*/
public ProcessingInstruction setPseudoAttribute(String name, String value) {
String reason = Verifier.checkProcessingInstructionData(name);
if (reason != null) {
throw new IllegalDataException(name, reason);
}
reason = Verifier.checkProcessingInstructionData(value);
if (reason != null) {
throw new IllegalDataException(value, reason);
}
this.mapData.put(name, value);
this.rawData = toString(mapData);
return this;
}
/**
* This will remove the pseudo attribute with the specified name.
*
* @param name name of pseudo attribute to remove
* @return <code>boolean</code> - whether the requested
* instruction was removed.
*/
public boolean removePseudoAttribute(String name) {
if ((mapData.remove(name)) != null) {
rawData = toString(mapData);
return true;
}
return false;
}
/**
* This will convert the Map to a string representation.
*
* @param mapData <code>Map</code> PI data to convert
* @return a string representation of the Map as appropriate for a PI
*/
private String toString(Map mapData) {
StringBuffer rawData = new StringBuffer();
Iterator i = mapData.keySet().iterator();
while (i.hasNext()) {
String name = (String)i.next();
String value = (String)mapData.get(name);
rawData.append(name)
.append("=\"")
.append(value)
.append("\" ");
}
// Remove last space, if we did any appending
if (rawData.length() > 0) {
rawData.setLength(rawData.length() - 1);
}
return rawData.toString();
}
/**
* This will parse and load the instructions for the PI.
* This is separated to allow it to occur once and then be reused.
*/
private Map parseData(String rawData) {
// The parsing here is done largely "by hand" which means the code
// gets a little tricky/messy. The following conditions should
// now be handled correctly:
// <?pi href="http://hi/a=b"?> Reads OK
// <?pi href = 'http://hi/a=b' ?> Reads OK
// <?pi href\t = \t'http://hi/a=b'?> Reads OK
// <?pi href = "http://hi/a=b"?> Reads OK
// <?pi?> Empty Map
// <?pi id=22?> Empty Map
// <?pi id='22?> Empty Map
Map data = new HashMap();
// System.out.println("rawData: " + rawData);
// The inputData variable holds the part of rawData left to parse
String inputData = rawData.trim();
// Iterate through the remaining inputData string
while (!inputData.trim().equals("")) {
//System.out.println("parseData() looking at: " + inputData);
// Search for "name =", "name=" or "name1 name2..."
String name = "";
String value = "";
int startName = 0;
char previousChar = inputData.charAt(startName);
int pos = 1;
for (; pos<inputData.length(); pos++) {
char currentChar = inputData.charAt(pos);
if (currentChar == '=') {
name = inputData.substring(startName, pos).trim();
// Get the boundaries on the quoted string
// We use boundaries so we know where to start next
int[] bounds = extractQuotedString(
inputData.substring(pos+1));
// A null value means a parse error and we return empty!
if (bounds == null) {
return new HashMap();
}
value = inputData.substring(bounds[0]+pos+1,
bounds[1]+pos+1);
pos += bounds[1] + 1; // skip past value
break;
}
else if (Character.isWhitespace(previousChar)
&& !Character.isWhitespace(currentChar)) {
startName = pos;
}
previousChar = currentChar;
}
// Remove the first pos characters; they have been processed
inputData = inputData.substring(pos);
// System.out.println("Extracted (name, value) pair: ("
// + name + ", '" + value+"')");
// If both a name and a value have been found, then add
// them to the data Map
if (name.length() > 0 && value != null) {
//if (data.containsKey(name)) {
// A repeat, that's a parse error, so return a null map
//return new HashMap();
//}
//else {
data.put(name, value);
//}
}
}
return data;
}
/**
* This is a helper routine, only used by parseData, to extract a
* quoted String from the input parameter, rawData. A quoted string
* can use either single or double quotes, but they must match up.
* A singly quoted string can contain an unbalanced amount of double
* quotes, or vice versa. For example, the String "JDOM's the best"
* is legal as is 'JDOM"s the best'.
*
* @param rawData the input string from which a quoted string is to
* be extracted.
* @return the first quoted string encountered in the input data. If
* no quoted string is found, then the empty string, "", is
* returned.
* @see #parseData
*/
private static int[] extractQuotedString(String rawData) {
// Remembers whether we're actually in a quoted string yet
boolean inQuotes = false;
// Remembers which type of quoted string we're in
char quoteChar = '"';
// Stores the position of the first character inside
// the quoted string (i.e. the start of the return string)
int start = 0;
// Iterate through the input string looking for the start
// and end of the quoted string
for (int pos=0; pos < rawData.length(); pos++) {
char currentChar = rawData.charAt(pos);
if (currentChar=='"' || currentChar=='\'') {
if (!inQuotes) {
// We're entering a quoted string
quoteChar = currentChar;
inQuotes = true;
start = pos+1;
}
else if (quoteChar == currentChar) {
// We're leaving a quoted string
inQuotes = false;
return new int[] { start, pos };
}
// Otherwise we've encountered a quote
// inside a quote, so just continue
}
}
return null;
}
/**
* This returns a <code>String</code> representation of the
* <code>ProcessingInstruction</code>, suitable for debugging. If the XML
* representation of the <code>ProcessingInstruction</code> is desired,
* {@link org.jdom.output.XMLOutputter#outputString(ProcessingInstruction)}
* should be used.
*
* @return <code>String</code> - information about the
* <code>ProcessingInstruction</code>
*/
public String toString() {
return new StringBuffer()
.append("[ProcessingInstruction: ")
.append(new org.jdom.output.XMLOutputter().outputString(this))
.append("]")
.toString();
}
/**
* This will return a clone of this <code>ProcessingInstruction</code>.
*
* @return <code>Object</code> - clone of this
* <code>ProcessingInstruction</code>.
*/
public Object clone() {
ProcessingInstruction pi = (ProcessingInstruction) super.clone();
// target and rawdata are immutable and references copied by
// Object.clone()
// Create a new Map object for the clone (since Map isn't Cloneable)
if (mapData != null) {
pi.mapData = parseData(rawData);
}
return pi;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -