💬

ITスクール DAY26 xmlParsing

2023/08/16に公開

始めに

先日は、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)の値を入れるためオーバーロードしました。

HyonHyonHttpClient
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,&lt,&gt,;]", "");
		System.out.println("제목 : " + t);
	   }else if(tagName.equals("description")) {
		t = xpp.getText();
		 t = t.replaceAll("[<b>,&apos,&lt,&gt,;]", "");
		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