You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析含&的XML遇SAXParseException,求无需修改XML的解决方法

解决未转义&的XML解析问题

遇到外部返回的XML包含未转义的&导致SAX解析报错时,无需修改原XML,可通过以下几种方式处理:

方法1:自定义输入流预处理XML

实现一个InputStream包装类,在读取数据时自动将未转义的&(非实体引用的&)替换为&,让JAXB拿到合法的XML再解析。

import java.io.*;

public class UnescapedAmpInputStream extends FilterInputStream {
    private StringBuilder buffer = new StringBuilder();
    private int pos = 0;

    protected UnescapedAmpInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        if (pos < buffer.length()) {
            return buffer.charAt(pos++);
        }
        int c = super.read();
        if (c == '&') {
            StringBuilder temp = new StringBuilder();
            temp.append((char)c);
            int next;
            // 检查后续字符是否是合法实体引用(比如&amp;)
            while ((next = super.read()) != -1 && temp.length() < 5) {
                temp.append((char)next);
                if (temp.toString().startsWith("&amp;")) {
                    buffer.append(temp);
                    pos = 0;
                    return buffer.charAt(pos++);
                }
            }
            // 不是合法实体,替换为&amp;并保留后续字符
            buffer.append("&amp;").append(temp.substring(1));
            pos = 0;
            return buffer.charAt(pos++);
        } else {
            return c;
        }
    }
}

使用方式:

// 外部XML的输入流
InputStream originalStream = new FileInputStream("savedsearch.xml");
InputStream processedStream = new UnescapedAmpInputStream(originalStream);

JAXBContext jaxbContext = JAXBContext.newInstance(MailSavedSearchRO.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
MailSavedSearchRO result = (MailSavedSearchRO) unmarshaller.unmarshal(processedStream);

方法2:用SAX过滤器拦截并转义字符

通过SAX的XMLFilter拦截字符事件,直接替换内容中的未转义&,再交给JAXB解析。

import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;

public class AmpEscapeFilter extends XMLFilterImpl {
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String content = new String(ch, start, length);
        // 只替换非标准实体的&
        String escapedContent = content.replaceAll("&(?!amp;|lt;|gt;|quot;|apos;)", "&amp;");
        super.characters(escapedContent.toCharArray(), 0, escapedContent.length());
    }
}

结合JAXB使用:

SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();

AmpEscapeFilter filter = new AmpEscapeFilter();
filter.setParent(xmlReader);

JAXBContext jaxbContext = JAXBContext.newInstance(MailSavedSearchRO.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setProperty("org.xml.sax.XMLReader", filter);

InputStream inputStream = new FileInputStream("savedsearch.xml");
MailSavedSearchRO result = (MailSavedSearchRO) unmarshaller.unmarshal(inputStream);

方法3:用非严格XML解析器转换格式

使用JTidy这类工具将格式不良的XML转换为合法XML,再进行JAXB解析。

先添加Maven依赖:

<dependency>
    <groupId>net.sf.jtidy</groupId>
    <artifactId>jtidy</artifactId>
    <version>r938</version>
</dependency>

代码实现:

import org.w3c.dom.Document;
import org.w3c.tidy.Tidy;
import java.io.FileInputStream;
import java.io.InputStream;

InputStream inputStream = new FileInputStream("savedsearch.xml");
Tidy tidy = new Tidy();
tidy.setXmlOut(true); // 指定输出XML格式
tidy.setShowWarnings(false);
tidy.setQuiet(true);

// 转换为合法的DOM文档
Document doc = tidy.parseDOM(inputStream, null);

JAXBContext jaxbContext = JAXBContext.newInstance(MailSavedSearchRO.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
MailSavedSearchRO result = (MailSavedSearchRO) unmarshaller.unmarshal(doc);

内容的提问来源于stack exchange,提问作者Sachin HR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:40:34