ITスクール DAY26 xmlParsing
始めに
先日は、apacheを利用して、サーバーからメッセージをもらう方法について勉強してみましたが、本日は、DB勉強に入る前に、データーを扱う練習として、サーバーからInputStreamと無料APIを活用することで、xmlをParsingする練習とHttpプロトコールを通してxml,htmlタグを入出力できる新しいクラスを作成しました。
Parsing
Parsing: データーを分解・組み合わせ自分が欲しい形に架空することです。
JSON, xmlの中で、無料APIの場合、xmlフォーマットで提供することが多いので、xmlParsingについて勉強します。
ライブラリクラス作成
InputStreamをリターンするメソッド(URL,URLConnection活用)
download(String address)
の場合、addressをURLのオブジェクトに作成、プロトコールによって異なるInputStreamをリターンするメソッドで、download(String address, HashMap<String,String> headers)
メソッドはAPIを活用するために必要なHeader(properties)の値を入れるためオーバーロードしました。
public class HyonHyonHttpClient {
public static InputStream download(String address) throws Exception {
URL u = new URL(address);
if(address.startsWith("https")){
HttpsURLConnection huc = (HttpsURLConnection) u.openConnection();
return huc.getInputStream();
}else {HttpURLConnection huc = (HttpURLConnection) u.openConnection();
return huc.getInputStream();
}
}
public static InputStream download(String address, HashMap<String, String> headers) throws Exception{
URL u = new URL(address);
if(address.startsWith("https")) {
HttpsURLConnection huc = (HttpsURLConnection) u.openConnection();
Set<String> headerName = headers.keySet();
for (String hn : headerName) {
huc.addRequestProperty(hn, headers.get(hn));
}
return huc.getInputStream();
}else {
HttpURLConnection huc = (HttpURLConnection) u.openConnection();
Set<String> headerName = headers.keySet();
for(String hn: headerName) {
huc.addRequestProperty(hn, headers.get(hn));
}
return huc.getInputStream();
}
}
データーをEncodingし、文字列にリターンするメソッド(StringBuffer活用)
エンコーディングフォーマットを選択できるInputStreamReaderにBufferedを付けて性能を上げました。InputStreamからReadしたサーバーのBody(html , xml)を文字列をリターンするため、
StringBufferをインスタンス化しました。
public static String convert(InputStream is, String charset) throws Exception{
InputStreamReader isr = new InputStreamReader(is,charset);
BufferedReader br = new BufferedReader(isr);
String line = null;
StringBuffer sb = new StringBuffer();
while((line= br.readLine())!= null) {
sb.append(line);
}
return sb.toString();
}
}
XmlPullParser
XML(Extensible Markup Language)
大規模のデーターの場合、普段DBを通して管理されますが、普通の人はSQL、Oracleを活用することが難しいです。DBのデーターをWEB上でも簡単にみることができるように表現したDBデーターの形式がxml,JSONになります。
データーの共有のためには、JSONの方がより幅広く使われ、よりシンプルな形のデーターですが、韓国の無料APIの場合、xmlを通してデーターを提供する場合が多いです。
xmlはデーターをhtmlのようにタグで表現した言語です。
<xxx> :StartTag (xxx:tagName)
yyy
</xxx> Endtag
HTML vs XML
使い方
HTMLはデーターを表示しますが XMLはデーターそのものを保存し、転送します。
タグ
HTMLは決まったタグがありますが、XMLは自分のタグを定義し、作ることができます。
Tagは、それぞれの整数値を持っており、その整数を利用しながら、Parsingを行います。
以下はxmlをInputStreamからインプットし、必要なデーターをtagの整数値とtagnameを通してデーターをるParsingするコードです。
import java.io.InputStream;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import com.hyonhyon.http.client.HyonHyonHttpClient;
//http://openAPI.seoul.go.kr:8088/(authorizingKey)/xml/RealtimeCityAir/1/25/
//authorizingKey :4f626857416f6c6c3632586a416843
public class AirPollutionMain1 {
public static void main(String[] args) throws Exception {
InputStream is = HyonHyonHttpClient.download("http://openAPI.seoul.go.kr:8088/4f626857416f6c6c3632586a416843/xml/RealtimeCityAir/1/25/");
XmlPullParserFactory xppf = XmlPullParserFactory.newInstance();
XmlPullParser xpp = xppf.newPullParser();
xpp.setInput(is,"UTF-8");
int type = xpp.getEventType();
String tagName = null;
while(type != XmlPullParser.END_DOCUMENT) {
if(type == XmlPullParser.START_TAG) {
tagName = xpp.getName();
}else if(type == XmlPullParser.TEXT) {
if(tagName.equals("MSRSTE_NM")) {
System.out.printf("%s : ", xpp.getText());
}else if(tagName.equals("PM10")) {
System.out.println(xpp.getText());
}
}else if(type == XmlPullParser.END_TAG) {
tagName = "";
}
xpp.next();
type = xpp.getEventType();
}
}
}
ライブラリクラスとXMLの活用
先ほど作成したHyonHyonHttpClientとXMLを活用して、検索したキーワードについてのニュースをゲットし、Parsingすることができます。
public static InputStream download(String address, HashMap<String, String> headers) throws Exception{
URL u = new URL(address);
if(address.startsWith("https")) {
HttpsURLConnection huc = (HttpsURLConnection) u.openConnection();
Set<String> headerName = headers.keySet();
for (String hn : headerName) {
huc.addRequestProperty(hn, headers.get(hn));
}
return huc.getInputStream();
}else {
HttpURLConnection huc = (HttpURLConnection) u.openConnection();
Set<String> headerName = headers.keySet();
for(String hn: headerName) {
huc.addRequestProperty(hn, headers.get(hn));
}
return huc.getInputStream();
}
}
HyonHyonHttpClientのメッソドはInputStreamとHashMapのentryのkey&value(properties)をサーバーに送るメソッドです。
public class NaverNewsMain {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)){
String address= "https://openapi.naver.com/v1/search/news.xml";
System.out.print("검색어: ");
String search = sc.nextLine();
System.out.println(search);
System.out.println();
search = URLEncoder.encode(search,"UTF-8");
address += "?query=" + search;
HashMap<String, String> headers =new HashMap<>();
headers.put("X-Naver-Client-Id","xXxXxXxXxXxXxX");
headers.put("X-Naver-Client-Secret","xXxXxXxXxX");
InputStream is = HyonHyonHttpClient.download(address,headers);
XmlPullParserFactory xppf = XmlPullParserFactory.newInstance();
XmlPullParser xpp = xppf.newPullParser();
xpp.setInput(is,"UTF-8");
int type = xpp.getEventType();
String tagName = null;
boolean data = false;
String t = null;
while(type != XmlPullParser.END_DOCUMENT) {
if(type == XmlPullParser.START_TAG) {
tagName = xpp.getName();
if(tagName.equals("item")) {
data = true;
}
}else if(type == XmlPullParser.TEXT) {
if(data) {
if(tagName.equals("title")) {
t = xpp.getText();
t = t.replaceAll("[<b>,&apos,<,>,;]", "");
System.out.println("제목 : " + t);
}else if(tagName.equals("description")) {
t = xpp.getText();
t = t.replaceAll("[<b>,&apos,<,>,;]", "");
System.out.println("내용 : " + t); System.out.println("=========================");
}
}
}else if(type == XmlPullParser.END_TAG) {
tagName = "";
}
xpp.next();
type = xpp.getEventType();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
Discussion