SAX パーサーを使用して、インターネットから変更できないドキュメントを解析しています。ドキュメントが次のようにフォーマットされたとき、それはうまく機能していました:
<outtertag>
<innertag>data</innertag>
<innerag>moreData</innertag>
</outtertag>
ただし、XML が外側のタグなしでフォーマットされている場合に行う特定の呼び出しがあるため、基本的に次のようなデータのリストのみを取得します。
<innertag>data</innertag>
<innerag>moreData</innertag>
これはばかげているように思えますが、XML のフォーマット方法を選択することはできず、今のところ変更することはできません。問題は、SAX パーサーが endDocument イベントを最初の終了タグにヒットするとすぐにヒットするように見えることです。
私は、InputStream を文字列に変換し、その周りにタグを投げてから、それを InputStream に変換するというかなりハックなソリューションを持っています。実際にはそのようにうまく解析されます。しかし、きっともっと良い方法があります。また、他のパーサー全体を作成したくありません。開始タグと終了タグがないことを除けば、ほとんどのタグは同じです。
念のため、コードを投稿しますが、これはかなり標準的な SAX パーサーです。オリジナルは、実際には約 30 個のタグを解析しています。
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
MyHandler handler = new MyHandler();
xmlReader.setContentHandler(handler);
InputSource inputSource = new InputSource(url.openStream());
xmlReader.parse(inputSource);
}
catch (SAXException e) { e.printStackTrace(); }
catch (ParserConfigurationException e) { e.printStackTrace(); }
catch(Exception e) { e.printStackTrace(); }
}
private class MyHandler extends DefaultHandler {
private StringBuilder content;
public MyHandler() {
content = new StringBuilder();
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
content = new StringBuilder();
if(localName.equalsIgnoreCase("innertag")) {
//Doing stuff
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
//Doing stuff
}
public void characters(char[] ch, int start, int length)
throws SAXException {
content.append(ch, start, length);
}
public void endDocument() throws SAXException {
//When parsing the second type of document, hits this event almost immediately after parsing first tag
}
}
そして、それが重要な場合は、これが私が使用しているハックコードですが、間違っているように感じますが、動作します:
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuilder sb = new StringBuilder("<tag>");
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
sb.append("</tag>");
String xml =sb.toString();
InputStream is = new ByteArrayInputStream(xml.getBytes());
InputSource source = new InputSource(is);
xmlReader.parse(source);