### Eclipse Workspace Patch 1.0 #P groovy-core Index: src/main/groovy/xml/MarkupBuilder.java =================================================================== --- src/main/groovy/xml/MarkupBuilder.java (revision 14844) +++ src/main/groovy/xml/MarkupBuilder.java (working copy) @@ -306,7 +306,7 @@ * @see #escapeXmlValue(String, boolean) */ private String escapeAttributeValue(String value) { - return escapeXmlValue(value, true); + return escapeXmlValue(value, true, useDoubleQuotes); } /** @@ -318,7 +318,7 @@ * @see #escapeXmlValue(String, boolean) */ private String escapeElementContent(String value) { - return escapeXmlValue(value, false); + return escapeXmlValue(value, false, useDoubleQuotes); } /** @@ -337,57 +337,47 @@ * * @param value The string to escape. * @param isAttrValue true if the string is to be used - * as an attribute value, otherwise false. + * as an attribute value, otherwise false. + * @param useDoubleQuotes true if double quotes are used + * as attribute delimiter, or false otherwise. * @return A new string in which all characters that require escaping * have been replaced with the corresponding XML entities. */ - private String escapeXmlValue(String value, boolean isAttrValue) { - StringBuffer buffer = new StringBuffer(value); - for (int i = 0, n = buffer.length(); i < n; i++) { - switch (buffer.charAt(i)) { + private static String escapeXmlValue(String value, + boolean isAttrValue, + boolean useDoubleQuotes) + { + if (value == null) + throw new IllegalArgumentException(); + + StringBuffer buffer = null; + + for (int i = 0, len = value.length(); i < len; i++) { + final char ch = value.charAt(i); + final String replacement; + + switch (ch) + { case '&': - buffer.replace(i, i + 1, "&"); - - // We're replacing a single character by a string of - // length 5, so we need to update the index variable - // and the total length. - i += 4; - n += 4; + replacement = "&"; break; case '<': - buffer.replace(i, i + 1, "<"); - - // We're replacing a single character by a string of - // length 4, so we need to update the index variable - // and the total length. - i += 3; - n += 3; + replacement = "<"; break; case '>': - buffer.replace(i, i + 1, ">"); - - // We're replacing a single character by a string of - // length 4, so we need to update the index variable - // and the total length. - i += 3; - n += 3; + replacement = ">"; break; case '"': // The double quote is only escaped if the value is for // an attribute and the builder is configured to output // attribute values inside double quotes. - if (isAttrValue && this.useDoubleQuotes) { - buffer.replace(i, i + 1, """); - - // We're replacing a single character by a string of - // length 6, so we need to update the index variable - // and the total length. - i += 5; - n += 5; - } + if (isAttrValue && useDoubleQuotes) + replacement = """; + else + replacement = null; break; case '\'': @@ -395,23 +385,34 @@ // attribute, as opposed to element content, and if the // builder is configured to surround attribute values with // single quotes. - if (isAttrValue && !this.useDoubleQuotes){ - buffer.replace(i, i + 1, "'"); - - // We're replacing a single character by a string of - // length 6, so we need to update the index variable - // and the total length. - i += 5; - n += 5; - } + if (isAttrValue && !useDoubleQuotes) + replacement = "'"; + else + replacement = null; break; default: + replacement = null; break; } + + if (replacement != null) { + // output differs from input; we write to our local buffer + if (buffer == null) { + buffer = new StringBuffer((int)(1.1 * len)); + buffer.append(value.substring(0, i)); + } + + buffer.append(replacement); + } else if (buffer != null) { + // output differs from input; we write to our local buffer + buffer.append(ch); + } else { + // nothing to do + } } - return buffer.toString(); + return buffer == null ? value : buffer.toString(); } private void toState(int next, Object name) {