Web版RSS閱讀器(一)——dom4j讀取xml(opml)檔案

來源:互聯網
上載者:User

      接觸java不久,偶有收穫,最近想做一個web版RSS閱讀器來鍛煉一下。手頭有幾個從不同版本的foxmail中匯出的opml檔案,大家應該都知道,opml檔案就是xml格式的。那麼就先從這裡入手,練習一下使用dom4j讀取xml檔案。


      在java程式設計中,尤其是java web開發程式,xml應用頻率超高。Spring、Hibernate、Struts等各種web 架構,MyEclipse、Oracle等IDE,也都主要依託xml。可以說xml對於系統的配置,有著至關重要的作用。而這些也同時增強了系統的靈活性。


      先說一下思路:

      建立一個java web項目,不過暫時沒有使用jsp,servlet。本文只是使用內建的調試器,先進行測試讀取xml。接下來的博文中,會帶大家一起顯示在已經最佳化的介面中,並提供大部分的rss閱讀器的功能。


      由於從不同版本的foxmail中匯出,檔案格式稍有不同,主要分歧是在訂閱分組功能上。有的版本匯出來的分組資訊是在head/title內容中,body/outline則放的是全部的訂閱資訊;有的匯出來的分組資訊則是在body/outline中title和text屬性中,而詳細的訂閱資訊則放在body/outline/outline中。


      我想做的系統可以支援讀取多個opml檔案,所以需要一個rss檔案清單設定檔【rss_config.xml】,對應一個實體:RssConfigBean.java,主要包含有opml檔案路徑資訊;分組資訊也需要單獨出來,命名為【RssTeamBean.java】,包括title和text兩個屬性和一個訂閱資訊的列表。訂閱資訊肯定也是獨立的,命名為【RssBean.java】,包括text、title、xmlUrl、htmlUrl、version、type六個屬性。


      首先通過讀取rss_config.xml,拿到所有opml檔案路徑,然後迴圈讀取opml,拿到分組資訊及每個分組下的所有詳細訂閱資訊,儲存到實體中,以供調用顯示。


      光說不管用,直接上代碼:

      ①. opml檔案

【單分組foxmail6.5.opml】

<?xml version="1.0"?><opml version="1.1"><head><title>六期新部落格地址</title></head><body><outline text="丁成雲" title="丁成雲" type="rss" version="RSS" xmlUrl="http://blog.csdn.net/sundenskyqq/rss/list" htmlUrl="http://blog.csdn.net/sundenskyqq" description=""/><outline text="韓正陽" title="韓正陽" type="rss" version="RSS" xmlUrl="http://blog.csdn.net/jiudihanbing/rss/list" htmlUrl="http://blog.csdn.net/jiudihanbing" description=""/></body></opml>

【多分組foxmail7.opml】

<?xml version="1.0" encoding="UTF-8"?><opml version="1.0"><head><title>Subscription in Foxmail</title></head><body><outline title="八期" text="八期"><outline htmlUrl="http://blog.csdn.net/shan9liang" xmlUrl="http://blog.csdn.net/shan9liang/rss/list" version="RSS" type="rss" title="賈琳" text="賈琳的專欄"/></outline><outline title="隨便看看" text="隨便看看"><outline htmlUrl="http://blog.csdn.net/blogdevteam" xmlUrl="http://blog.csdn.net/blogdevteam/rss/list" version="RSS" type="rss" title="CSDN 官方部落格" text="CSDN 官方部落格"/><outline htmlUrl="http://blog.csdn.net/zhoufoxcn" xmlUrl="http://blog.csdn.net/zhoufoxcn/rss/list" version="RSS" type="rss" title="周公的專欄" text="周公的專欄"/></outline><outline title="提高班" text="提高班"><outline htmlUrl="http://sxyandapp.blog.163.com" xmlUrl="http://sxyandapp.blog.163.com/rss" version="RSS" type="rss" title="石小永" text="石小永"/><outline htmlUrl="http://blog.csdn.net/qiulongtianshi" xmlUrl="http://blog.csdn.net/qiulongtianshi/rss/list" version="RSS" type="rss" title="郭校林" text="郭校林"/></outline></body></opml>

②. 在src中建立rss檔案清單設定檔

【rss_config.xml】

<?xml version="1.0" encoding="UTF-8"?><rss><rss-list><rss-name>單分組foxmail6.5</rss-name><rss-path>\rss\單分組foxmail6.5.opml</rss-path></rss-list><rss-list><rss-name>多分組foxmail7</rss-name><rss-path>\rss\多分組foxmail7.opml</rss-path></rss-list></rss>

③. 建立包com.tgb.rssreader.bean,添加3個java檔案:

【RssBean.java】詳細訂閱資訊

package com.tgb.rssreader.bean;/** * 詳細訂閱資訊 * @author Longxuan * */public class RssBean {/** * 顯示名稱 */private String text;/** * 標題 */private String title;/** * rss訂閱地址 */private String htmlUrl;/** * rss訂閱地址 */private String xmlUrl;/** * 版本 */private String version;/** * 類型 */private String type;public String getText() {return text;}public void setText(String text) {this.text = text;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getHtmlUrl() {return htmlUrl;}public void setHtmlUrl(String htmlUrl) {this.htmlUrl = htmlUrl;}public String getXmlUrl() {return xmlUrl;}public void setXmlUrl(String xmlUrl) {this.xmlUrl = xmlUrl;}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}public String getType() {return type;}public void setType(String type) {this.type = type;}}

【RssConfigBean.java】 rss配置資訊

package com.tgb.rssreader.bean;/** * rss配置資訊 * @author Longxuan * */public class RssConfigBean {/** * 分組名稱 */private String name;/** * 路徑 */private String path;public String getPath() {return path;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void setPath(String path) {this.path = path;}}

【RssTeamBean.java】rss分組資訊

package com.tgb.rssreader.bean;import java.util.List;/** * rss分組資訊 * @author Longxuan * */public class RssTeamBean {/** * 分組標題 */private String title;/** * 分組名稱 */private String text;private List<RssBean> rssBeanList ;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getText() {return text;}public void setText(String text) {this.text = text;}public List<RssBean> getRssBeanList() {return rssBeanList;}public void setRssBeanList(List<RssBean> rssBeanList) {this.rssBeanList = rssBeanList;}}

④. 建立包com.tgb.rssreader.manager,添加2個檔案:

【RssConfigMgr.java】rss檔案清單組態管理員

package com.tgb.rssreader.manager;import java.io.InputStream;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import com.tgb.rssreader.bean.RssConfigBean;/** * rss檔案清單組態管理員 * @author Longxuan * */public class RssConfigMgr {/** * 讀取rss檔案清單配置資訊 * @return */public List<RssConfigBean> getRssConfig() {List<RssConfigBean> list = new ArrayList<RssConfigBean>();RssConfigBean rssConfigBean = null;InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("rss_config.xml");if (is == null) {//System.out.println("找不到該檔案");//return null;throw new RuntimeException("找不到rss_config.xml檔案");}try {// 讀取並解析XML文檔// SAXReader就是一個管道,用一個流的方式,把xml檔案讀出來SAXReader reader = new SAXReader(); // 下面的是通過解析xml字串的Document doc = reader.read(is);Element rootElt = doc.getRootElement(); // 擷取根節點//System.out.println("根節點:" + rootElt.getName()); // 拿到根節點的名稱Iterator<?> iter = rootElt.elementIterator("rss-list"); // 擷取根節點下的子節點rss-list// 遍曆rss-list節點while (iter.hasNext()) {Element recordEle = (Element) iter.next();String name = recordEle.elementTextTrim("rss-name"); // 拿到rss-list節點下的子節點name值//System.out.println("name:" + name);String path = recordEle.elementTextTrim("rss-path"); // 拿到rss-list節點下的子節點path值//System.out.println("path:" + path);rssConfigBean = new RssConfigBean();//儲存到rssConfigBean中rssConfigBean.setName(name);rssConfigBean.setPath(path);//儲存到list中list.add(rssConfigBean);}} catch (DocumentException e) {e.printStackTrace();}return list;}}

【ReadXML.java】讀取xml檔案

package com.tgb.rssreader.manager;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import com.tgb.rssreader.bean.RssBean;import com.tgb.rssreader.bean.RssConfigBean;import com.tgb.rssreader.bean.RssTeamBean;/** * 讀取xml檔案 * @author Longxuan * */public class ReadXML {// rss分組訂閱列表private List<RssTeamBean> rssTeamBeanList = new ArrayList<RssTeamBean>();/** * 讀取rss檔案清單 */public void ReadRss() {// rss檔案清單配置資訊實體RssConfigMgr rssConfigMgr = new RssConfigMgr();List<RssConfigBean> list = rssConfigMgr.getRssConfig();String errText = "";// 記錄錯誤資訊// 迴圈讀取rss檔案清單for (RssConfigBean rssConfig : list) {// System.out.println(rssConfig.getName() + "----" +// rssConfig.getPath());try {// 讀取rss檔案內容ReadRss(System.getProperty("user.dir")+ rssConfig.getPath());} catch (Exception e) {errText += e.getMessage();}}}/** * 讀取ompl檔案 *  * @param filePath */private void ReadRss(String filePath) {File file = new File(filePath);if (!file.exists()) {// System.out.println("找不到【" + filePath + "】檔案");// return;throw new RuntimeException("找不到【" + filePath + "】檔案");}try {// 讀取並解析XML文檔// SAXReader就是一個管道,用一個流的方式,把xml檔案讀出來SAXReader reader = new SAXReader();FileInputStream fis = new FileInputStream(file);// 下面的是通過解析xml字串的Document doc = reader.read(fis);// 擷取根節點Element rootElt = doc.getRootElement(); // 擷取根節點// System.out.println("根節點:" + rootElt.getName()); // 拿到根節點的名稱// 擷取head/title節點Element titleElt = (Element) rootElt.selectSingleNode("head/title");// 擷取head節點下的子節點title// 擷取分組名稱String title = titleElt.getTextTrim();// 擷取body節點Element bodyElt = (Element) rootElt.selectSingleNode("body");// 擷取body下的第一個outline節點Element outlineElt = (Element) bodyElt.selectSingleNode("outline");// 判斷該outlineElt節點的屬性數量,>2說明是詳細部落格訂閱資訊,否則則是分組資訊。if (outlineElt.attributes().size() > 2) { // 詳細部落格訂閱資訊// 執行個體化 RSS分組實體RssTeamBean rssTeamBean = new RssTeamBean();// 擷取body節點下的outline節點Iterator<?> iter = bodyElt.elementIterator("outline");// 輸出分組名稱// System.out.println("分組名稱:" + title);// 記錄分組名稱rssTeamBean.setTitle(title);rssTeamBean.setText(title);// 執行個體化訂閱列表List<RssBean> rssBeanList = new ArrayList<RssBean>();// 擷取詳細部落格訂閱資訊ReadBlogsInfo(iter, rssBeanList);// 設定訂閱列表到分組中rssTeamBean.setRssBeanList(rssBeanList);// 添加分組到rss分組訂閱列表rssTeamBeanList.add(rssTeamBean);} else { // 分組資訊// 擷取body節點下的outline節點Iterator<?> iter = bodyElt.elementIterator("outline");while (iter.hasNext()) {// 讀取outline節點下的所有outline資訊,每條資訊都是一條訂閱記錄Element TeamElt = (Element) iter.next();// 執行個體化 RSS分組實體RssTeamBean rssTeamBean = new RssTeamBean();// 重新擷取分組名稱title = TeamElt.attributeValue("title");String text = TeamElt.attributeValue("text");// System.out.println("分組title:" + title + "   text:" +// text);// 記錄分組名稱和顯示名稱rssTeamBean.setTitle(title);rssTeamBean.setText(text);// 執行個體化訂閱列表List<RssBean> rssBeanList = new ArrayList<RssBean>();// 擷取body節點下的outline節點Iterator<?> iterRss = TeamElt.elementIterator("outline");// 擷取詳細部落格訂閱資訊ReadBlogsInfo(iterRss, rssBeanList);// 設定訂閱列表到分組中rssTeamBean.setRssBeanList(rssBeanList);// 添加分組到rss分組訂閱列表rssTeamBeanList.add(rssTeamBean);}}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (DocumentException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/** * 讀取當前組部落格訂閱資訊 *  * @param iter *            當前節點的子節點迭代器 * @param rssBeanList *            訂閱列表 */private void ReadBlogsInfo(Iterator<?> iter, List<RssBean> rssBeanList) {// 遍曆所有outline節點,每個節點都是一條訂閱資訊while (iter.hasNext()) {RssBean rssBean = new RssBean();Element outlineElt = (Element) iter.next();String htmlUrl = outlineElt.attributeValue("htmlUrl"); // 拿到當前節點的htmlUrl屬性值String xmlUrl = outlineElt.attributeValue("xmlUrl"); // 拿到當前節點的xmlUrl屬性值String version = outlineElt.attributeValue("version"); // 拿到當前節點的version屬性值String type = outlineElt.attributeValue("type"); // 拿到當前節點的type屬性值String outlineTitle = outlineElt.attributeValue("title"); // 拿到當前節點的title屬性值String outlineText = outlineElt.attributeValue("text"); // 拿到當前節點的text屬性值// System.out.print("<outline htmlUrl=\"" + htmlUrl + "\" ");// System.out.print("xmlUrl=\"" + xmlUrl + "\" ");// System.out.print("version=\"" + version + "\" ");// System.out.print("type=\"" + type + "\" ");// System.out.print("title=\"" + outlineTitle + "\" ");// System.out.println("text=\"" + outlineText + "\" />");rssBean.setHtmlUrl(htmlUrl);rssBean.setXmlUrl(xmlUrl);rssBean.setVersion(version);rssBean.setType(type);rssBean.setTitle(outlineTitle);rssBean.setText(outlineText);rssBean.setText(outlineText);// 將每條訂閱資訊,存放到訂閱列表中rssBeanList.add(rssBean);}}/** * 擷取Rss分組訂閱列表 *  * @return */public List<RssTeamBean> getRssTemBeanList() {return rssTeamBeanList;}public static void main(String[] args) {ReadXML readXML = new ReadXML();readXML.ReadRss();List<RssTeamBean> rssTemBeanList = readXML.getRssTemBeanList();for (RssTeamBean rssTeamBean : rssTemBeanList) {System.out.println("【分組title:" + rssTeamBean.getTitle() + "   text:"+ rssTeamBean.getText()+"】");for (RssBean rssBean : rssTeamBean.getRssBeanList()) { System.out.print("<outline htmlUrl=\"" + rssBean.getHtmlUrl() + "\" "); //System.out.print("xmlUrl=\"" + rssBean.getXmlUrl() + "\" "); System.out.print("version=\"" + rssBean.getVersion() + "\" "); System.out.print("type=\"" + rssBean.getType() + "\" "); System.out.print("title=\"" +  rssBean.getTitle() + "\" "); System.out.println("text=\"" + rssBean.getText() + "\" />");}System.out.println("-------------------------------------------------");}}}

      由於沒有使用jsp進行顯示,所以要想看效果,直接右鍵main函數,選擇“Run As”-》“1 Java Application” ,進行測試。這裡給出:



      已經可以完全讀取了。不論是單組舊版的,還是多分組新版匯出來的opml檔案,都可以正常讀取。接下來的博文中,會寫怎麼把結果讀取到jsp,會使用樹結構來顯示。後續版本會加上添加,刪除,修改,移動訂閱資訊及複製訂閱資訊到組。同時也提供匯入,匯出功能。這些都會出現在後續部落格中。盡請期待。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.