ห้องสมุดส่วนใหญ่เสนอการหลบหนีทุกอย่างที่ทำได้รวมถึงสัญลักษณ์หลายร้อยตัวและอักขระที่ไม่ใช่ ASCII หลายพันตัวซึ่งไม่ใช่สิ่งที่คุณต้องการในโลก UTF-8
นอกจากนี้ดังที่ Jeff Williams ตั้งข้อสังเกตไม่มีตัวเลือก“ escape HTML” เดียวมีหลายบริบท
สมมติว่าคุณไม่เคยใช้แอททริบิวที่ยังไม่ได้อ้างถึงและระลึกไว้เสมอว่ามีบริบทที่แตกต่างกันมันได้เขียนเวอร์ชั่นของฉันเอง:
private static final long BODY_ESCAPE =
1L << '&' | 1L << '<' | 1L << '>';
private static final long DOUBLE_QUOTED_ATTR_ESCAPE =
1L << '"' | 1L << '&' | 1L << '<' | 1L << '>';
private static final long SINGLE_QUOTED_ATTR_ESCAPE =
1L << '"' | 1L << '&' | 1L << '\'' | 1L << '<' | 1L << '>';
// 'quot' and 'apos' are 1 char longer than '#34' and '#39' which I've decided to use
private static final String REPLACEMENTS = ""&'<>";
private static final int REPL_SLICES = /* |0, 5, 10, 15, 19, 23*/
5<<5 | 10<<10 | 15<<15 | 19<<20 | 23<<25;
// These 5-bit numbers packed into a single int
// are indices within REPLACEMENTS which is a 'flat' String[]
private static void appendEscaped(
StringBuilder builder,
CharSequence content,
long escapes // pass BODY_ESCAPE or *_QUOTED_ATTR_ESCAPE here
) {
int startIdx = 0, len = content.length();
for (int i = 0; i < len; i++) {
char c = content.charAt(i);
long one;
if (((c & 63) == c) && ((one = 1L << c) & escapes) != 0) {
// -^^^^^^^^^^^^^^^ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// | | take only dangerous characters
// | java shifts longs by 6 least significant bits,
// | e. g. << 0b110111111 is same as >> 0b111111.
// | Filter out bigger characters
int index = Long.bitCount(SINGLE_QUOTED_ATTR_ESCAPE & (one - 1));
builder.append(content, startIdx, i /* exclusive */)
.append(REPLACEMENTS,
REPL_SLICES >>> 5*index & 31,
REPL_SLICES >>> 5*(index+1) & 31);
startIdx = i + 1;
}
}
builder.append(content, startIdx, len);
}
พิจารณาการคัดลอกจากGist โดยไม่จำกัดความยาวของบรรทัดสรุปสาระสำคัญได้โดยไม่ต้องเส้นขีดจำกัดความยาว