SAX Xml->SAXParseException在文档的元素内容中找到无效的 XML 字符 (Unicode: 0x10)

本文介绍了一种在使用SAX解析大型XML文件时遇到含有unicode字符导致SAXParseException的方法,通过设置继续解析选项,实现了忽略错误记录或特殊处理错误记录,避免了解析过程因错误而终止。

在用SAX解析xml时,遇到文件中含unicode字符,则会抛出SAXParseException。

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="12">
        <name>Spring in Action</name>
        <price>45.0</price>
    </book>
    <book id="15">
        <name>HG6201M     </name>
        <price>39.0</price>
    </book>
</books>
其实当文件较大时,部分某一条的数据并不是很重要,我们希望能够略过这条数据或对这条数据作特殊处理,而不是当遇到解析错误时终止解析。

参考如下:

MyHander handler = new MyHander();
InputStream is = Test.class.getClass().getResourceAsStream("/file/book.xml");
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader reader = factory.newSAXParser().getXMLReader();
//关键设置
reader.setFeature("http://apache.org/xml/features/continue-after-fatal-error",true);
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
reader.parse(new InputSource(is));

自定义Hander:

public class ParseXmlHandler extends DefaultHandler {

    private String tag;
    private StringBuffer sb = null;

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        tag = qName;
        sb = new StringBuffer();
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        tag = null;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (tag != null) {
            if (sb == null) {
                System.out.println("error");
            } else {
                sb.append(ch, start, length);
                System.out.println(sb.toString());
            }
        }
    }

    @Override
    public void fatalError(SAXParseException e) throws SAXException {
        sb = null;
    }
}

源码解析:

1.查找到当解析错误时抛出异常的类

可以看到在XMLErrorReporter.java中有段代码,当fContinueAfterFatalError为false时则解析抛出异常。

case SEVERITY_FATAL_ERROR: {
    errorHandler.fatalError(domain, key, parseException);
    if (!fContinueAfterFatalError) {
       throw parseException;
    }
    break;
}
则应设置fContinueAfterFatalError为true,该类的setFeature方法则可以设置fContinueAfterFatalError的属性


查看其常量值进行对应的设置

    public static final String XERCES_FEATURE_PREFIX = "http://apache.org/xml/features/";
    public static final String CONTINUE_AFTER_FATAL_ERROR_FEATURE = "continue-after-fatal-error";


解析XML文档时出现“invalid XML character Unicode 0x1”错误,通常是因为XML解析器在解析文档内容时遇到了不被允许的控制字符XML 1.0规范中定义了一些字符为非法字符,例如ASCII控制字符(如Unicode 0x1、0x1f、0x18等),这些字符XML文档中无法直接使用,必须进行转义或删除[^4]。 ### 常见原因与解决方案 #### 1. **非法字符存在于XML内容中** XML文档中可能直接包含了ASCII控制字符(如0x1等),这些字符通常不可见,但在解析时会导致异常。这种情况常见于从数据库导出数据或从外部系统接收的数据中包含非法字符。 **解决方案:** - **预处理XML内容**:在解析前,使用正则表达式过滤掉非法字符。例如,可以使用Java代码对字符串进行处理: ```java String cleanedXml = rawXml.replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]", ""); ``` 这段代码会移除所有ASCII控制字符(除了换行符和制表符)[^2]。 - **使用第三方库处理**:可以使用Apache Commons Text等库中的方法清理非法字符: ```java import org.apache.commons.text.StringEscapeUtils; String cleanedXml = StringEscapeUtils.escapeXml10(rawXml); ``` #### 2. **使用SAX解析器处理大文件时跳过错误** 如果XML文件较大,并且某些数据行包含非法字符但不是关键数据,可以考虑使用SAX解析器,并在遇到错误时跳过非法内容。 **解决方案:** - **自定义ErrorHandler**:通过实现`org.xml.sax.ErrorHandler`接口,可以在解析过程中捕获错误并决定是否继续解析。 ```java public class CustomErrorHandler implements ErrorHandler { @Override public void warning(SAXParseException exception) throws SAXException { // 忽略警告 } @Override public void error(SAXParseException exception) throws SAXException { // 忽略错误 } @Override public void fatalError(SAXParseException exception) throws SAXException { // 忽略致命错误 } } ``` 在构建解析器时设置该错误处理器,可以避免解析因非法字符而中断。 #### 3. **使用CDATA处理特殊内容** 如果非法字符出现在文本节点中,可以尝试将这些内容包裹在`<![CDATA[ ... ]]>`中,这样解析器会将其视为纯文本,不会进行解析。 **示例:** ```xml <property column="name"><![CDATA[Some text with invalid character \x01]]></property> ``` 这种方式可以有效避免因特殊字符导致的解析错误[^1]。 #### 4. **验证XML文档的合法性** 在解析之前,可以使用在线XML验证工具或本地XML校验工具(如XMLSpy、Oxygen XML Editor等)检查XML文档的结构和字符合法性。这些工具通常会指出具体的错误位置和类型,便于快速定位问题。 #### 5. **确保编码一致性** 确保XML文档的编码声明与实际存储的编码一致。例如,如果文档声明为UTF-8,但实际使用了其他编码(如GBK),可能会导致解析器误读某些字节为非法字符。 **解决方案:** -XML文件开头明确声明编码: ```xml <?xml version="1.0" encoding="UTF-8"?> ``` - 使用文本编辑器或转换工具确保文件的实际编码与声明一致。 --- ### 总结 处理XML解析时遇到的非法字符问题,主要思路是**预处理内容、使用合适的解析策略、确保编码一致性**。根据具体情况选择合适的方法,可以有效避免解析错误并提高系统的健壮性。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值