
本文介绍通过自定义 prettyprintwriter 子类,绕过 xstream 默认的 xml 字符转义(如将 `'` 转为 `'`),实现原始文本(含单引号、双引号等)直出,同时兼顾 `&` 和 `
在使用 XStream 进行 XML 序列化时,PrettyPrintWriter 会自动对特殊字符执行 XML 实体转义:例如单引号 ' 被转为 ',双引号 " 变为 ",& 变为 &,仅对真正危险的字符转义,而放行 '、" 等在大多数上下文中安全的字符。
解决思路是继承 PrettyPrintWriter 并重写 writeText(QuickWriter, String) 方法——该方法负责向 XML 文本节点内容写入字符串。默认实现会调用 QuickWriter.writeEncoded() 执行全量转义;我们可替换为选择性转义逻辑。
以下是一个生产就绪的自定义写入器示例:
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import java.io.Writer;
public class LenientPrettyPrintWriter extends PrettyPrintWriter {
public LenientPrettyPrintWriter(Writer writer) {
super(writer);
}
@Override
public void writeText(QuickWriter writer, String text) {
if (text == null) return;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case '&': sb.append("&"); break;
case '<': sb.append("<"); break;
case '>': sb.append(">"); break;
// 允许 ' 和 " 直接输出(XML 中合法)
default: sb.append(c); break;
}
}
writer.write(sb.toString());
}
}使用方式与原生 PrettyPrintWriter 完全一致:
XStream xstream = new XStream();
try (FileWriter fw = new FileWriter("output.xml")) {
String payload = "It's \"safe\" to use <tags> & symbols here.";
xstream.marshal(payload, new LenientPrettyPrintWriter(fw));
}生成的 XML 片段为:
<string>It's "safe" to use <tags> & symbols here.</string>
✅ 成功保留了 ' 和 " 的原始形式;
✅ 仍严格转义了 &、 —— 这三项是 XML 解析器必须识别的“致命字符”,不可省略;
❌ 不处理属性值(attribute value):若需控制属性中的转义,请额外重写 writeAttributeValue(QuickWriter, String) 方法(通常无需改动)。
⚠️ 重要提醒:
- 此方案输出的 XML 仍是完全合法且可被任何标准 XML 解析器正确读取的(因为 ' 和 " 属于可选转义,而 &/</> 是强制要求);
- 若下游系统无法识别 ',问题根源在于其 XML 解析能力不足,更推荐修复接收方而非妥协输出规范;
- 绝对避免完全禁用所有转义(如直接 writer.write(string)),否则一旦输入含 & 或
综上,定制 writeText 是精准控制文本内容转义粒度的专业方案——在合规前提下实现所需表现力。










