SAX解析器:忽略特殊字符

Ale*_*kov 8 java xml parsing sax saxparser

我正在使用Xerces来解析我的xml文档.问题是xml转义了像' '这样的字符 在characters()方法中显示为非转义的.我需要在characters()方法中获取转义字符.

谢谢.

UPD:尝试覆盖我的DefaultHandler后代的resolveEntity方法.从调试中可以看出它被设置为xml阅读器的实体解析器,但是没有调用来自重写方法的代码.

jav*_*nna 7

我认为你的解决方案并不是太糟糕:几行代码可以完全按照你的意愿行事.问题是,startEntityendEntity没有被提供的方法ContentHandler接口,所以你必须写LexicalHandler它结合你的工作ContentHandler.通常,使用a XMLFilter更优雅,但你必须使用实体,所以你仍然应该写一个LexicalHandler.请看这里介绍SAX过滤器的使用.

我想向您展示一种与您非常相似的方法,它允许您将&输出操作(或其他包装)与过滤操作(包装等)分开.我写了自己XMLFilterXMLFilterImpl,也实现了LexicalHandler接口.此过滤器仅包含与entites escape/unescape相关的代码.

public class XMLFilterEntityImpl extends XMLFilterImpl implements
        LexicalHandler {

    private String currentEntity = null;

    public XMLFilterEntityImpl(XMLReader reader)
            throws SAXNotRecognizedException, SAXNotSupportedException {
        super(reader);
        setProperty("http://xml.org/sax/properties/lexical-handler", this);
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        if (currentEntity == null) {
            super.characters(ch, start, length);
            return;
        }

        String entity = "&" + currentEntity + ";";
        super.characters(entity.toCharArray(), 0, entity.length());
        currentEntity = null;
    }

    @Override
    public void startEntity(String name) throws SAXException {
        currentEntity = name;
    }

    @Override
    public void endEntity(String name) throws SAXException {
    }

    @Override
    public void startDTD(String name, String publicId, String systemId)
            throws SAXException {
    }

    @Override
    public void endDTD() throws SAXException {
    }

    @Override
    public void startCDATA() throws SAXException {
    }

    @Override
    public void endCDATA() throws SAXException {
    }

    @Override
    public void comment(char[] ch, int start, int length) throws SAXException {
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的主,附DefaultHandler作为ContentHandler其接收实体,因为它是根据过滤器的代码:

public static void main(String[] args) throws ParserConfigurationException,
        SAXException, IOException {

    DefaultHandler defaultHandler = new DefaultHandler() {
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            //This method receives the entity as is
            System.out.println(new String(ch, start, length));
        }
    };

    XMLFilter xmlFilter = new XMLFilterEntityImpl(XMLReaderFactory.createXMLReader());
    xmlFilter.setContentHandler(defaultHandler);
    String xml = "<html><head><title>title</title></head><body>&amp;</body></html>";
    xmlFilter.parse(new InputSource(new StringReader(xml)));
}
Run Code Online (Sandbox Code Playgroud)

这是我的输出:

title
&amp;
Run Code Online (Sandbox Code Playgroud)

可能你不喜欢它,无论如何这是一个替代解决方案.

对不起,SaxParser我认为你没有更优雅的方式.

您还应该考虑切换到StaxParser:XMLInputFactory.IS_REPLACING_ENTITY_REFERENCE设置为false 可以很容易地执行您想要的操作.如果你喜欢这个解决方案,你应该看看这里.


Mic*_*Kay 5

如果您提供LexicalHandler作为SAX解析器的回调,它将使用startEntity()和endEntity()回调通知您每个实体引用的开始和结束.

(请注意,当正确的术语是"实体引用"时,http://download.oracle.com/javase/1.5.0/docs/api/org/xml/sax/ext/LexicalHandler.html上的JavaDoc会讨论"实体" ").

另请注意,无法让SAX解析器告诉您有关数字字符引用的信息,例如&#x1234;.应用程序应该以与原始角色完全相同的方式处理它们,所以你真的不应该对它们感兴趣.