在 Java 中处理 XML,特别是涉及到读取或写入 XML 数据的场景时,经常会遇到需要对 XML 内容进行编码或解码的情况。特别是在涉及到 XML 元素的文本内容(InnerText)时,自动转义(或称为字符实体引用)是非常重要的,以防止 XML 解析错误或安全漏洞,比如 XML 注入攻击。
1. XML 内容的自动转义
在 Java 中,当需要将字符串写入 XML 文件时,通常需要确保这些字符串中的特殊字符被正确地转义。例如,<, >, &, " 和 ' 这些字符在 XML 中有特殊的含义,因此它们需要被转换成相应的实体引用(如 <, >, &, ", 和 ')。
2. 使用 Java 标准库处理 XML
使用 org.w3c.dom
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class XmlExample {
public static void main(String\[\] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("root");
doc.appendChild(root);
Element element = doc.createElement("element");
root.appendChild(element);
// 使用 Text 节点添加内容,并自动转义特殊字符
element.appendChild(doc.createTextNode("<example> & text"));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
}
}
使用 javax.xml.bind (JAXB)
如果使用 JAXB 来序列化 Java 对象到 XML,JAXB 会自动处理字符的转义
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class JAXBExample {
public static void main(String\[\] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(MyObject.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
MyObject obj = new MyObject();
obj.setContent("<example> & text");
marshaller.marshal(obj, System.out);
}
}
3. 手动处理转义和反转义
如果需要手动处理字符串的转义和反转义,可以使用 Apache Commons Text 或手动编写方法:
import org.apache.commons.text.StringEscapeUtils;
public class ManualEscape {
public static void main(String\[\] args) {
String original = "<example> & text";
String escaped = StringEscapeUtils.escapeXml10(original); // Apache Commons Text 库进行转义
System.out.println("Escaped: " + escaped); // 输出: <example> & text
}
}
或者手动实现:
public class ManualEscape {
public static String escapeXml(String input) {
return input.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
public static void main(String\[\] args) {
String original = "<example> & text";
String escaped = escapeXml(original); // 手动转义
System.out.println("Escaped: " + escaped); // 输出: <example> & text
}
}
结论
在 Java 中处理 XML 时,确保对特殊字符进行