微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 如果在输入文件中没有指定一个SAX解析器,如何强制使用DTD?

如果在输入文档中没有任何文字类型的情况下解析文档时,如何强制使用SAX解析器(特别是 Java中的Xerces)来使用DTD?这是甚么可能吗?

以下是我的场景的更多细节:

我们有一堆XML文档符合由多个不同系统生成的相同DTD(我不能更改).其中一些系统在其输出文档中添加一个doctype,另一些则不会.有些使用命名字符实体,有些不行.有些使用命名字符实体,而不声明一个doctype.我知道这不是犹太教,但这是我必须合作的.

我正在使用需要在Java中解析这些文件的系统.目前,它正在处理上述情况,首先将XML文档作为流读取,尝试检测是否定义了一个doctype,如果尚未存在,则添加一个doctype声明.问题是这个代码错误的,我想用更清洁的东西替换它.

文件很大,所以我不能使用基于DOM的解决方案.我也试图解决字符实体,所以它不利于使用XML模式.

如果你有一个解决方案,你可以直接发布,而不是链接到它?如果在未来有一个正确的解决方案与死链接,它不会做堆栈溢出很好.

解决方法

我认为设置DOCTYPE是不合理的方式,如果文档没有.可能的解决方案是写假的,就像你已经做的那样.如果您使用SAX,您可以使用这个假的InputStream和假的DefaultHandler实现. (仅适用于latin1一字节编码)

我知道这个解决方案也是丑陋的,但只有一个适用于大数据流.

这是一些代码.

private enum State {readxmlDec,readxmlDecEnd,writeFakeDoctipe,writeEnd};

private class MyInputStream extends InputStream{

    private final InputStream is;
    private StringBuilder sb = new StringBuilder();
    private int pos = 0;
    private String doctype = "<!DOCTYPE register SYstem \"fake.dtd\">";
    private State state = State.readxmlDec;

    private MyInputStream(InputStream source) {
        is = source;
    }
    @Override
    public int read() throws IOException {
        int bit;

        switch (state){ 
            case readxmlDec:
                bit = is.read();
                sb.append(Character.tochars(bit));
                if(sb.toString().equals("<?xml")){
                    state = State.readxmlDecEnd;
                }
                break;
            case readxmlDecEnd:
                bit = is.read();
                if(Character.tochars(bit)[0] == '>'){
                    state = State.writeFakeDoctipe;
                }
                break;
            case writeFakeDoctipe:
                bit =  doctype.charat(pos++);
                if(doctype.length() == pos){
                    state = State.writeEnd;
                }
                break;
            default:
                bit = is.read();
                break;
        }
        return bit;
    }

    @Override
    public void close() throws IOException {
        super.close();
        is.close();
    }
}

private static class MyHandler extends DefaultHandler {

    @Override
    public InputSource resolveEntity(String publicId,String systemId) throws IOException,SAXException {
        System.out.println("resolve "+ systemId);
        // get real dtd
        InputStream is = ClassLoader.class.getResourceAsstream("/register.dtd");
        return new InputSource(is);
    }

 ... // rest of code
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


应用场景 C端用户提交工单、工单创建完成之后、会发布一条工单创建完成的消息事件(异步消息)、MQ消费者收到消息之后、会通知各处理器处理该消息、各处理器处理完后都会发布一条将该工单写入搜索引擎的消息、最终该工单出现在搜索引擎、被工单处理人检索和处理。 事故异常体现 1、异常体现 从工单的流转记录发现、
线程类,设置有一个公共资源 package cn.org.chris.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Descrip
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量
Java 9中JShell中的不同启动脚本是什么?
使用Java的位填充错误检测技术
java中string是什么
如何使用Java中的JSON-lib API将Map转换为JSON对象?