2

私はこれがここで何度も尋ねられたことを知っています、しかし私はそれを扱う別の問題を抱えています。私の場合、アプリは文字列として渡された整形式ではないdom構造を受け取ります。これがサンプルです:

<div class='video yt'><div class='yt_url'>http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata</div></div>

ご覧のとおり、内容は整形式ではありません。ここで、通常のSAXまたはDOM解析を使用して解析しようとすると、理解できる例外がスローされます。

org.xml.sax.SAXParseException:エンティティ「feature」への参照は「;」で終わる必要があります デリミタ。

要件に従って、このドキュメントを読み、divタグをいくつか追加して、コンテンツを文字列として送り返す必要があります。これは、入力構造を読み取り、必要な位置にタグを追加できるため、DOMパーサーを使用することでうまく機能します。

JTidyなどのツールを使用して前処理を実行してから解析しようとしましたが、その結果、ドキュメントが本格的なhtmlに変換されてしまいます。これは望ましくありません。サンプルコードは次のとおりです。


StringWriter writer = new StringWriter();
Tidy tidy = new Tidy(); // obtain a new Tidy instance
tidy.setXHTML(true);
tidy.parse(new ByteArrayInputStream(content.getBytes()), writer);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(writer.toString().getBytes()));
// Traverse thru the content and add new tags
....
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);

これにより、入力が整形式のhtmlドキュメントに完全に変換されます。そうすると、htmlタグを手動で削除することが難しくなります。私が試したもう1つのオプションは、SAX2DOMを使用することでした。これもHTMLドキュメントを作成します。これがサンプルコードです。


ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes());     
Parser p = new Parser();
p.setFeature(IContentExtractionConstant.SAX_NAMESPACE,true);
SAX2DOM sax2dom = new SAX2DOM();
p.setContentHandler(sax2dom);
p.parse(new InputSource(is));
Document doc = (Document)sax2dom.getDOM();

誰かが彼らの考えを共有することができれば私は感謝します。

ありがとう

4

1 に答える 1

1

最も簡単な方法は、xml予約文字を対応するxmlエンティティに置き換えることです。これは手動で行うことができます。

content.replaceAll("&", "&amp;");

文字列を解析する前に変更したくない場合は、を使用して別の方法を提案できますSaxParserが、このソリューションはより複雑です。基本的にあなたはしなければなりません:

  1. LexicalHandlerと組み合わせて書くContentHandler
  2. 致命的なエラーの後で実行を続行するようにパーサーに指示します( 十分でErrorHandlerはありません)
  3. 宣言されていないエンティティを単純なテキストとして扱います

更新
あなたのコメントによると、私は2番目の解決策に関するいくつかの詳細を追加するつもりです。拡張(、、、およびのDefaulHandlerデフォルトの実装)およびを実装するクラスを作成しました。のメソッドを拡張し(私の実装は例外をスローする代わりに何もしません)、のメソッドと組み合わせて機能するメソッドを拡張しました。EntityResolverDTDHandlerContentHandlerErrorHandlerLexicalHandlerErrorHandlerfatalErrorContentHandlercharactersstartEntityLexicalHandler

public class MyHandler extends DefaultHandler implements LexicalHandler {

    private String currentEntity = null;

    @Override
    public void fatalError(SAXParseException e) throws SAXException {
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String content = new String(ch, start, length);
        if (currentEntity != null) {
            content = "&" + currentEntity + content;
            currentEntity = null;
        }
        System.out.print(content);
    }

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

これは、整形式ではないxmlを解析する私のメインです。これがないと、実装が空であるにもかかわらずsetFeatureパーサーがスローするため、これは非常に重要です。SaxParseExceptionErrorHandler

public static void main(String[] args) throws ParserConfigurationException,
        SAXException, IOException {
    String xml = "<div class='video yt'><div class='yt_url'>http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata</div></div>";
    SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
    XMLReader xmlReader = saxParser.getXMLReader();
    MyHandler myHandler = new MyHandler();
    xmlReader.setContentHandler(myHandler);
    xmlReader.setErrorHandler(myHandler);
    xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler",
            myHandler);
    xmlReader.setFeature(
            "http://apache.org/xml/features/continue-after-fatal-error",
            true);
    xmlReader.parse(new InputSource(new StringReader(xml)));
}

このメインは、エラーを含むdiv要素のコンテンツを出力します。

http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata

これは入力で機能する例であることに注意してください。おそらく、入力を完了する必要があります。たとえば、一部の文字を正しくエスケープしている場合は、この状況を処理するためにコードを数行追加する必要があります。

お役に立てれば。

于 2011-04-11T12:42:43.843 に答える