1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.sun.syndication.io.impl;
18
19 import com.sun.syndication.feed.WireFeed;
20 import com.sun.syndication.feed.rss.Channel;
21 import com.sun.syndication.feed.rss.Description;
22 import com.sun.syndication.feed.rss.Image;
23 import com.sun.syndication.feed.rss.Item;
24 import org.jdom.Attribute;
25 import org.jdom.DocType;
26 import org.jdom.Document;
27 import org.jdom.Element;
28 import org.jdom.Namespace;
29
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.Map;
35
36 /***
37 */
38 public class RSS091Parser extends RSS090Parser {
39
40 public RSS091Parser() {
41 this("rss_0.91");
42 }
43
44 protected RSS091Parser(String type) {
45 super(type);
46 }
47
48 public boolean isMyType(Document document) {
49 boolean ok = false;
50 Element rssRoot = document.getRootElement();
51 ok = rssRoot.getName().equals("rss");
52 if (ok) {
53 ok = false;
54 Attribute version = rssRoot.getAttribute("version");
55 if (version!=null) {
56 ok = version.getValue().equals(getRSSVersion());
57 }
58 }
59 return ok;
60 }
61
62 protected String getRSSVersion() {
63 return "0.91";
64 }
65
66 private static final String USERLAND = "Userland";
67 private static final String NETSCAPE = "Netscape";
68
69 private static final String ELEMENT_NAME = "rss";
70 private static final String PUBLIC_ID = "-//Netscape Communications//DTD RSS 0.91//EN";
71 private static final String SYSTEM_ID = "http://my.netscape.com/publish/formats/rss-0.91.dtd";
72
73 private String getVariant(Document document) {
74 String variant = USERLAND;
75 DocType docType = document.getDocType();
76
77 if (docType!=null) {
78 boolean ok = ELEMENT_NAME.equals(docType.getElementName());
79 ok = ok && PUBLIC_ID.equals(docType.getPublicID());
80 ok = ok && SYSTEM_ID.equals(docType.getSystemID());
81 if (ok) {
82 variant = NETSCAPE;
83 }
84 }
85 return variant;
86 }
87
88 protected Namespace getRSSNamespace() {
89 return Namespace.getNamespace("");
90 }
91
92 protected boolean isHourFormat24(Element rssRoot) {
93 String variant = getVariant((Document)rssRoot.getParent());
94 return variant.equals(USERLAND);
95 }
96
97 /***
98 * Parses the root element of an RSS document into a Channel bean.
99 * <p/>
100 * It first invokes super.parseChannel and then parses and injects the following
101 * properties if present: language, pubDate, rating and copyright.
102 * <p/>
103 *
104 * @param rssRoot the root element of the RSS document to parse.
105 * @return the parsed Channel bean.
106 */
107 protected WireFeed parseChannel(Element rssRoot) {
108 Channel channel = (Channel) super.parseChannel(rssRoot);
109
110 Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
111
112 Element e = eChannel.getChild("language",getRSSNamespace());
113 if (e!=null) {
114 channel.setLanguage(e.getText());
115 }
116 e = eChannel.getChild("rating",getRSSNamespace());
117 if (e!=null) {
118 channel.setRating(e.getText());
119 }
120 e = eChannel.getChild("copyright",getRSSNamespace());
121 if (e!=null) {
122 channel.setCopyright(e.getText());
123 }
124 e = eChannel.getChild("pubDate",getRSSNamespace());
125 if (e!=null) {
126 channel.setPubDate(DateParser.parseRFC822(e.getText()));
127 }
128 e = eChannel.getChild("lastBuildDate",getRSSNamespace());
129 if (e!=null) {
130 channel.setLastBuildDate(DateParser.parseRFC822(e.getText()));
131 }
132 e = eChannel.getChild("docs",getRSSNamespace());
133 if (e!=null) {
134 channel.setDocs(e.getText());
135 }
136 e = eChannel.getChild("docs",getRSSNamespace());
137 if (e!=null) {
138 channel.setDocs(e.getText());
139 }
140 e = eChannel.getChild("managingEditor",getRSSNamespace());
141 if (e!=null) {
142 channel.setManagingEditor(e.getText());
143 }
144 e = eChannel.getChild("webMaster",getRSSNamespace());
145 if (e!=null) {
146 channel.setWebMaster(e.getText());
147 }
148 e = eChannel.getChild("skipHours");
149 if (e!=null) {
150 List skipHours = new ArrayList();
151 List eHours = e.getChildren("hour",getRSSNamespace());
152 for (int i=0;i<eHours.size();i++) {
153 Element eHour = (Element) eHours.get(i);
154 skipHours.add(new Integer(eHour.getText()));
155 }
156 channel.setSkipHours(skipHours);
157 }
158
159 e = eChannel.getChild("skipDays");
160 if (e!=null) {
161 List skipDays = new ArrayList();
162 List eDays = e.getChildren("day",getRSSNamespace());
163 for (int i=0;i<eDays.size();i++) {
164 Element eDay = (Element) eDays.get(i);
165 skipDays.add(DAYS.get(eDay.getText()));
166 }
167 channel.setSkipDays(skipDays);
168 }
169 return channel;
170 }
171
172 private static final Map DAYS = new HashMap();
173
174 static {
175 DAYS.put(Channel.SUNDAY.toString(),Channel.SUNDAY);
176 DAYS.put(Channel.MONDAY.toString(),Channel.MONDAY);
177 DAYS.put(Channel.TUESDAY.toString(),Channel.TUESDAY);
178 DAYS.put(Channel.WEDNESDAY.toString(),Channel.WEDNESDAY);
179 DAYS.put(Channel.THURSDAY.toString(),Channel.THURSDAY);
180 DAYS.put(Channel.FRIDAY.toString(),Channel.FRIDAY);
181 DAYS.put(Channel.SATURDAY.toString(),Channel.SATURDAY);
182 }
183
184 /***
185 * Parses the root element of an RSS document looking for image information.
186 * <p/>
187 * It first invokes super.parseImage and then parses and injects the following
188 * properties if present: url, link, width, height and description.
189 * <p/>
190 *
191 * @param rssRoot the root element of the RSS document to parse for image information.
192 * @return the parsed RSSImage bean.
193 */
194 protected Image parseImage(Element rssRoot) {
195 Image image = super.parseImage(rssRoot);
196 if (image!=null) {
197 Element eImage = getImage(rssRoot);
198 Element e = eImage.getChild("width",getRSSNamespace());
199 if (e!=null) {
200 image.setWidth(Integer.parseInt(e.getText()));
201 }
202 e = eImage.getChild("height",getRSSNamespace());
203 if (e!=null) {
204 image.setHeight(Integer.parseInt(e.getText()));
205 }
206 e = eImage.getChild("description",getRSSNamespace());
207 if (e!=null) {
208 image.setDescription(e.getText());
209 }
210 }
211 return image;
212 }
213
214
215 /***
216 * It looks for the 'item' elements under the 'channel' elemment.
217 */
218 protected List getItems(Element rssRoot) {
219 Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
220 return (eChannel!=null) ? eChannel.getChildren("item",getRSSNamespace()) : Collections.EMPTY_LIST;
221 }
222
223 /***
224 * It looks for the 'image' elements under the 'channel' elemment.
225 */
226 protected Element getImage(Element rssRoot) {
227 Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
228 return (eChannel!=null) ? eChannel.getChild("image",getRSSNamespace()) : null;
229 }
230
231 /***
232 * It looks for the 'textinput' elements under the 'channel' elemment.
233 */
234 protected Element getTextInput(Element rssRoot) {
235 String variant = getVariant((Document)rssRoot.getParent());
236 String elementName = (variant.equals(USERLAND)) ? "textInput" : "textinput";
237 Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
238 return (eChannel!=null) ? eChannel.getChild(elementName,getRSSNamespace()) : null;
239 }
240
241 /***
242 * Parses an item element of an RSS document looking for item information.
243 * <p/>
244 * It first invokes super.parseItem and then parses and injects the description property if present.
245 * <p/>
246 *
247 * @param rssRoot the root element of the RSS document in case it's needed for context.
248 * @param eItem the item element to parse.
249 * @return the parsed RSSItem bean.
250 */
251 protected Item parseItem(Element rssRoot,Element eItem) {
252 Item item = super.parseItem(rssRoot,eItem);
253 Element e = eItem.getChild("description",getRSSNamespace());
254 if (e!=null) {
255 item.setDescription(parseItemDescription(rssRoot,e));
256 }
257 return item;
258 }
259
260 protected Description parseItemDescription(Element rssRoot,Element eDesc) {
261 Description desc = new Description();
262 desc.setType("text/plain");
263 desc.setValue(eDesc.getText());
264 return desc;
265 }
266
267 }