Я думаю, что ваше решение не так уж и плохо: несколько строк кода, чтобы сделать именно то, что вы хотите.Проблема в том, что методы startEntity
и endEntity
не предоставляются интерфейсом ContentHandler
, поэтому вы должны написать LexicalHandler
, который работает в сочетании с вашим ContentHandler
.Обычно использование XMLFilter
более элегантно, но вы должны работать с сущностью, поэтому вам все равно следует написать LexicalHandler
.Взгляните здесь на введение в использование фильтров SAX.
Я хотел бы показать вам способ, очень похожий на ваш, который позволяет вам разделять операции фильтрации (обертывание& to &
например) от операций вывода (или чего-то еще).Я написал свой собственный XMLFilter
на основе XMLFilterImpl
, который также реализует интерфейс 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 {
}
}
И это мой основной метод, с 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.Если вам нравится это решение, вы должны взглянуть здесь .