RSSデータ部分をオブジェクトにして扱ってみる。
前回の例題でRSSを外部からもってくるコードを書いてみたのだけど、単純なハッシュでは中に入れられるデータがどうしても限られてしまう。でも Javaに構造体はない 。じゃあどうする?簡単だ、小さなクラスをひとつ定義すればいい。
そんなわけで、先日の議題をちょっといじくり、RSSオブジェクトをぶっちあげて使ってみる事にした。
「クラスてなんやねん」って方はオブジェクト指向プログラミングの本でも読んでください。とりあえずごく簡単に私個人の理解を述べれば、たとえば「パソコンとは」という枠組みを決めているんだと考えてます。
で「パソコンである」というだけでは使い物にならないですよね?だからその中に「キーボードは日本語用」「モニターがここについていて液晶」「電源ボタンはここにある」という風なローカルなデータがあり、それから「電源ボタンを押したらこうなる」「モニターのつまみをひねったら…」みたいな『メソッド』を盛りこんで実際に動けるようにするんですね。でもまぁ、当然だけどゼロからこんなもの作ると面倒このうえないわけで、似たような物が既にある場合はそれを元にして作る事もできる。これがつまり『継承』ってやつ。
で、実際に使うには、たとえば変数を一個用意して「おまえはパソコンだ」と初期化してから使えばいいと。あとは「パソコンの電源いれて」「パソコンのモニターこっち向けて」と明快に指示してやれば、その通りに動くというからくりだ。
どうだろう。もちろん詳しい人からすれば「それで説明したつもりかよ!」と激怒されそうだけど、とりあえずこの程度の理解でも疑問なく使うことはできると思う。
さて、では早速すすめていこう。
static class Rsss{ String title = ""; String url = ""; String date = ""; String fdate = ""; static String format(String date){ String r = date; String rr = ""; String[] m = "Dummy,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(",",0); Pattern pattern = Pattern.compile("(Mon|Tue|Wed|Thu|Fri|Sat|Sun),"); Matcher matcher = pattern.matcher(r); r = matcher.replaceAll(""); r = Pattern.compile(" +").matcher(r).replaceAll(" "); r = Pattern.compile(" (\\d{1,2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (20\\d{2})").matcher(r).replaceAll("$3/$2/$1"); for(int i=1;i<13;i++){ rr = r; r = Pattern.compile(m[i]).matcher(r).replaceAll(String.valueOf(i)); if(!r.equals(rr)){ r = Pattern.compile("(/)(\\d)(/)").matcher(r).replaceAll("$1"+"0"+"$2$3"); } } r = r.trim(); return(r); } }
複雑なものではないのでゼロから作った。NetBeansだとどう処理するのかと思ってたけど、 class置き場にガーッとまとめて吐き出す みたいですね。*.jar構築する事考えたら結局まぁそれでいいのか。納得。
タイトル、URL、日付をちゃんと別々に取り扱うようにした。で、日付変換もこちらに突っ込んでしまった。相変わらずの間に合わせである。
で、前回の項目 2のa)とb)、つまりRSS取り込み&処理部分も少しだけ変わる。ハッシュでなくアレイリストにするのだ。つまりこのRSSクラスのオブジェクトをそのまんまぶちこんでやるわけだ。変に細工してテキスト入れるより美しいね XD
なお一件だけ注意。classの中のデータ定義をstaticで書かないように。これやると、どうもクラスごと配列に突っ込んだりして動かそうとすると内容が上書きされたりおかしな挙動を起こすのだ。まぁstaticだからねと言われればそれまでなんだけど。このへん要注意みたいだ。いや、私がバカなだけど言われればそれまでなんですが XD
ほとんど変わってないけど、ハッシュマップがただのアレイリストになり、Rssオブジェクトをnew(変数にわりあてて初期化)してaddするあたりが変わっている。
static ArrayList<Rsss> xmlAnl3(String fn){ ArrayList<Rsss> s = new ArrayList<Rsss>(); try { DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder bulder=factory.newDocumentBuilder(); InputStream input=new URL(fn).openStream(); Document dc=bulder.parse(input); NodeList list=dc.getElementsByTagName("item"); for(int i=0;i<list.getLength();i++){ Node n=list.item(i); NodeList nlist=n.getChildNodes(); String title=null; String url=null; String date=null; for(int j=0;j<nlist.getLength();j++){ Node child=nlist.item(j); if(child.getNodeName().equals("title")){ title=child.getTextContent().trim(); }else if(child.getNodeName().equals("link")){ url=child.getTextContent().trim(); }else if(child.getNodeName().equals("pubDate")){ date=child.getTextContent().trim(); } if(title!=null && url!=null && date!=null){ Rsss sx = new Rsss(); sx.title = title; sx.url = url; sx.date = date; sx.fdate = sx.format(date); s.add(sx); break; } } } }catch(ParserConfigurationException e){ e.printStackTrace(); }catch(SAXException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } return(s); }
んで、これを読みだしてGUIに吐き出すコード。出力が変わったのでそれに合わせただけ。
@Action public void getNhkNews() { String x = ""; String x2 = ""; ArrayList<String> s = loadRsss("setup.xml"); for(int i=0;i<s.size();i++){ x2 = ""; if(s.get(i).indexOf("http://") == 0){ ArrayList<Rsss> ss = xmlAnl3(s.get(i)); for (int ii = 0;ii<ss.size();ii++){ x2 = x2 + "<li><a href=\""+","+ss.get(ii).url+"\">"+ss.get(ii).fdate+", "+ss.get(ii).title+"</a></li>"; } } if(x2 != ""){ x = x + "<ul>" + x2 + "</ul>"; } } if(x != ""){ jeditpane1.setText(x); } }
そろそろ見づらいのが気になってきたところだ。次回はJListを使ってみるか。