我认为你的解决方案并不是太糟糕:几行代码可以完全按照你的意愿行事.问题是,startEntity并endEntity没有被提供的方法ContentHandler接口,所以你必须写LexicalHandler它结合你的工作ContentHandler.通常,使用a XMLFilter更优雅,但你必须使用实体,所以你仍然应该写一个LexicalHandler.请看这里介绍SAX过滤器的使用.
我想向您展示一种与您非常相似的方法,它允许您将&输出操作(或其他包装)与过滤操作(包装等)分开.我写了自己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 {
}
}
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>&</body></html>";
xmlFilter.parse(new InputSource(new StringReader(xml)));
}
Run Code Online (Sandbox Code Playgroud)
这是我的输出:
title
&
Run Code Online (Sandbox Code Playgroud)
可能你不喜欢它,无论如何这是一个替代解决方案.
对不起,SaxParser我认为你没有更优雅的方式.
您还应该考虑切换到StaxParser:XMLInputFactory.IS_REPLACING_ENTITY_REFERENCE设置为false 可以很容易地执行您想要的操作.如果你喜欢这个解决方案,你应该看看这里.
如果您提供LexicalHandler作为SAX解析器的回调,它将使用startEntity()和endEntity()回调通知您每个实体引用的开始和结束.
(请注意,当正确的术语是"实体引用"时,http://download.oracle.com/javase/1.5.0/docs/api/org/xml/sax/ext/LexicalHandler.html上的JavaDoc会讨论"实体" ").
另请注意,无法让SAX解析器告诉您有关数字字符引用的信息,例如ሴ.应用程序应该以与原始角色完全相同的方式处理它们,所以你真的不应该对它们感兴趣.