私はあなたの解決策はそれほど悪くはないと思います:あなたが望むことを正確に行うための数行のコード。問題はstartEntity
、endEntity
メソッドがContentHandler
インターフェースによって提供されないことです。そのため、LexicalHandler
と組み合わせて機能するを作成する必要がありますContentHandler
。通常、anの使用XMLFilter
はより洗練されていますが、エンティティを操作する必要があるため、。を記述する必要がありますLexicalHandler
。SAXフィルターの使用法の概要については、こちらをご覧ください。
&
フィルタリング操作(たとえば、ラッピング&to)を出力操作(または他の何か)から分離できる、あなたの方法と非常によく似た方法を紹介したいと思います。インターフェースも実装しているものXMLFilter
に基づいて自分で作成しました。このフィルターには、エスケープ/エスケープ解除に関連するコードのみが含まれています。XMLFilterImpl
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
asがあります。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
も検討する必要があります。falseにXMLInputFactory.IS_REPLACING_ENTITY_REFERENCE
設定すると、やりたいことが非常に簡単になります。このソリューションが気に入った場合は、こちらをご覧ください。