我认为您的解决方案还不错:几行代码就可以完全按照您的意愿行事。
问题是startEntity 和endEntity 方法不是由ContentHandler 接口提供的,因此您必须编写一个LexicalHandler 与您的ContentHandler 结合使用。
通常,XMLFilter 的使用更优雅,但是你必须使用实体,所以你仍然应该写一个LexicalHandler。看看here 了解 SAX 过滤器的使用。
我想向您展示一种与您的方法非常相似的方法,它允许您将过滤操作(例如包装 & 到 &)与输出操作(或其他操作)分开。我已经基于XMLFilterImpl 编写了我自己的XMLFilter,它也实现了LexicalHandler 接口。此过滤器仅包含与实体转义/取消转义相关的代码。
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 {
}
}
这是我的主要内容,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>&</body></html>";
xmlFilter.parse(new InputSource(new StringReader(xml)));
}
这是我的输出:
title
&
可能你不喜欢它,反正这是一个替代解决方案。
很抱歉,但是对于SaxParser,我认为您没有更优雅的方式。
您还应该考虑切换到StaxParser:将XMLInputFactory.IS_REPLACING_ENTITY_REFERENCE 设置为false 很容易做您想做的事。如果你喜欢这个解决方案,你应该看看here。