8

Xercesを使用してXMLドキュメントを解析しています。問題は、XMLでエスケープされた文字がメソッドにエスケープされていない文字として 表示されることです。メソッドcharacters()内でエスケープ文字をそのまま取得する必要があります。characters()

ありがとう。

UPD:私の子孫のresolveEntity()メソッドをオーバーライドしようとしました。DefaultHandlerデバッグから、XMLリーダーへのエンティティリゾルバーとして設定されていることがわかりますが、オーバーライドされたメソッドからのコードは呼び出されません。

4

4 に答える 4

7

私はあなたの解決策はそれほど悪くはないと思います:あなたが望むことを正確に行うための数行のコード。問題はstartEntityendEntityメソッドがContentHandlerインターフェースによって提供されないことです。そのため、LexicalHandlerと組み合わせて機能するを作成する必要がありますContentHandler。通常、anの使用XMLFilterはより洗練されていますが、エンティティを操作する必要があるため、。を記述する必要がありますLexicalHandler。SAXフィルターの使用法の概要については、こちらをご覧ください。

&フィルタリング操作(たとえば、ラッピング&to)を出力操作(または他の何か)から分離できる、あなたの方法と非常によく似た方法を紹介したいと思います。インターフェースも実装しているものXMLFilterに基づいて自分で作成しました。このフィルターには、エスケープ/エスケープ解除に関連するコードのみが含まれています。XMLFilterImplLexicalHandler

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 {
    }
}

そして、これが私のメインであり、フィルターコードに従ってエンティティをそのまま受け取るDefaultHandlerasがあります。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)));
}

そしてこれは私の出力です:

title
&amp;

おそらくあなたはそれが気に入らないでしょう、とにかくこれは代替の解決策です。

申し訳ありSaxParserませんが、これ以上エレガントな方法はないと思います。

また、次のように切り替えることStaxParserも検討する必要があります。falseにXMLInputFactory.IS_REPLACING_ENTITY_REFERENCE設定すると、やりたいことが非常に簡単になります。このソリューションが気に入った場合は、こちらをご覧ください。

于 2011-04-02T17:55:25.543 に答える
5

SAX パーサーへのコールバックとして LexicalHandler を指定すると、startEntity() および endEntity() コールバックを使用して、すべてのエンティティ参照の開始と終了が通知されます。

( http://download.oracle.com/javase/1.5.0/docs/api/org/xml/sax/ext/LexicalHandler.htmlの JavaDoc では、正しい用語が「エンティティ参照」である場合に「エンティティ」について説明していることに注意してください。 」)。

また、SAX パーサーに&#x1234;. アプリケーションはこれらを元のキャラクターとまったく同じように扱うことになっているので、実際には興味を持ってはいけません。

于 2011-03-29T16:09:38.390 に答える
1

一時的な解決策:

public void startEntity(String name) throws SAXException {
    inEntity = true;
    entityName = name;
}

public void characters(char[] ch, int start, int length) throws SAXException {
    String data;
    if (inEntity) {
        inEntity = false;
        data = "&" + entityName + ";";
    } else {
        data = new String(ch, start, length);
    }
    //TODO do something instead of System.out
    System.out.println(data);
}

しかし、それでもエレガントなソリューションが必要です。

于 2011-03-30T14:26:29.553 に答える
1

もう 1 つ may:クラスescapeXmlのメソッドがあり ます。org.apache.commons.lang.StringEscapeUtils

characters(char[] ch, int start, int length)メソッドで次のコードを試してください。

String data=new String(ch, start, length);
String escapedData=org.apache.commons.lang.StringEscapeUtils.escapeXml(data);

jarはこちらからダウンロードできます。

于 2011-04-05T11:46:18.517 に答える