1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
package org.apache.commons.feedparser; |
18 | |
|
19 | |
import java.util.Iterator; |
20 | |
import java.util.List; |
21 | |
|
22 | |
import org.jaxen.jdom.JDOMXPath; |
23 | |
import org.jdom.Attribute; |
24 | |
import org.jdom.Element; |
25 | |
|
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | 0 | public class RSSFeedParser extends BaseParser { |
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
public static void parse( FeedParserListener listener, |
40 | |
org.jdom.Document doc ) throws Exception { |
41 | |
|
42 | 0 | FeedParserState state = new FeedParserState( listener ); |
43 | |
|
44 | 0 | FeedVersion v = new FeedVersion(); |
45 | |
|
46 | 0 | v.isRSS = true; |
47 | 0 | v.version = doc.getRootElement().getAttributeValue( "version" ); |
48 | |
|
49 | 0 | listener.onFeedVersion( v ); |
50 | |
|
51 | 0 | listener.init(); |
52 | |
|
53 | |
|
54 | 0 | JDOMXPath xpath = new JDOMXPath( "/descendant::*[local-name() = 'channel']" ); |
55 | 0 | Element channel = (Element)xpath.selectSingleNode( doc ); |
56 | 0 | state.current = channel; |
57 | |
|
58 | 0 | doLocale( state, listener, channel ); |
59 | 0 | doChannel( listener, state ); |
60 | 0 | doLocaleEnd( state, listener, channel ); |
61 | |
|
62 | |
|
63 | 0 | xpath = new JDOMXPath( "/descendant::*[local-name() = 'image']" ); |
64 | 0 | List images = xpath.selectNodes( doc ); |
65 | 0 | Iterator i = images.iterator(); |
66 | |
|
67 | 0 | while ( i.hasNext() ) { |
68 | |
|
69 | 0 | Element child = (Element)i.next(); |
70 | 0 | state.current = child; |
71 | 0 | doParseImage( listener, state ); |
72 | |
|
73 | 0 | } |
74 | |
|
75 | |
|
76 | 0 | xpath = new JDOMXPath( "/descendant::*[local-name() = 'item']" ); |
77 | |
|
78 | 0 | List items = xpath.selectNodes( doc ); |
79 | |
|
80 | 0 | i = items.iterator(); |
81 | |
|
82 | |
|
83 | 0 | while ( i.hasNext() ) { |
84 | |
|
85 | 0 | Element item = (Element)i.next(); |
86 | |
|
87 | 0 | state.current = item; |
88 | |
|
89 | 0 | doLocale( state, listener, item ); |
90 | 0 | doItem( listener, state ); |
91 | 0 | doLocaleEnd( state, listener, item ); |
92 | |
|
93 | 0 | } |
94 | |
|
95 | 0 | listener.finished(); |
96 | |
|
97 | 0 | } |
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
private static void doChannel( FeedParserListener listener, |
105 | |
FeedParserState state ) throws Exception { |
106 | |
|
107 | 0 | String link = getChildElementTextByName( state, "link" ); |
108 | |
|
109 | 0 | if ( link != null ) |
110 | 0 | link = link.trim(); |
111 | |
|
112 | 0 | listener.onChannel( state, |
113 | |
getChildElementTextByName( state, "title" ), |
114 | |
link, |
115 | |
getChildElementTextByName( state, "description" ) ); |
116 | |
|
117 | 0 | listener.onChannelEnd(); |
118 | |
|
119 | 0 | } |
120 | |
|
121 | |
|
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
private static void doParseImage( FeedParserListener listener, |
127 | |
FeedParserState state ) throws Exception { |
128 | |
|
129 | 0 | String title = getChildElementTextByName( state, "title" ); |
130 | 0 | String link = getChildElementTextByName( state, "link" ); |
131 | 0 | String url = getChildElementTextByName( state, "url" ); |
132 | |
|
133 | 0 | if ( url != null ) { |
134 | 0 | listener.onImage( state, title, link, url ); |
135 | 0 | listener.onImageEnd(); |
136 | |
|
137 | |
} |
138 | |
|
139 | 0 | } |
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
private static void doItem( FeedParserListener listener, |
147 | |
FeedParserState state ) throws Exception { |
148 | |
|
149 | 0 | String resource = null; |
150 | |
|
151 | |
|
152 | |
|
153 | 0 | JDOMXPath xpath = new JDOMXPath( "@rdf:resource|guid|descendant::*[local-name() = 'link']" ); |
154 | 0 | xpath.addNamespace( NS.RDF.getPrefix(), NS.RDF.getURI() ); |
155 | 0 | Object node = xpath.selectSingleNode( state.current ); |
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | 0 | if ( node instanceof Element ) { |
161 | |
|
162 | 0 | Element element = (Element)node; |
163 | 0 | resource = element.getText(); |
164 | |
|
165 | 0 | if ( "guid".equals( element.getName() ) ) { |
166 | |
|
167 | 0 | boolean isPermaLink = |
168 | |
"true".equals( element.getAttributeValue( "isPermaLink" ) ); |
169 | |
|
170 | 0 | if ( isPermaLink == false ) { |
171 | |
|
172 | |
|
173 | 0 | Element link = state.current.getChild( "link" ); |
174 | |
|
175 | 0 | if ( link != null ) { |
176 | 0 | resource = link.getText(); |
177 | |
} |
178 | |
|
179 | |
} |
180 | |
|
181 | |
} |
182 | |
|
183 | 0 | } else if ( node instanceof Attribute ) { |
184 | 0 | resource = ((Attribute)node).getValue(); |
185 | |
} |
186 | |
|
187 | 0 | if ( resource == null ) |
188 | 0 | return; |
189 | |
|
190 | |
|
191 | |
|
192 | 0 | listener.onItem( state, |
193 | |
getChildElementTextByName( state, "title" ), |
194 | |
getChildElementTextByName( state, "link" ), |
195 | |
getChildElementTextByName( state, "description" ), |
196 | |
resource ); |
197 | |
|
198 | |
|
199 | |
|
200 | 0 | if ( listener instanceof ModContentFeedParserListener ) { |
201 | |
|
202 | 0 | ModContentFeedParserListener mcpl = (ModContentFeedParserListener)listener; |
203 | |
|
204 | 0 | Element encoded = state.current.getChild( "encoded", NS.CONTENT ); |
205 | |
|
206 | 0 | if ( encoded != null ) { |
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | 0 | mcpl.onContentEncoded( new FeedParserState( encoded ), |
212 | |
encoded.getText() ); |
213 | |
|
214 | 0 | mcpl.onContentEncodedEnd(); |
215 | |
|
216 | |
} else { |
217 | |
|
218 | 0 | Element items = state.current.getChild( "items", NS.CONTENT ); |
219 | |
|
220 | 0 | if ( items != null ) { |
221 | |
|
222 | |
|
223 | |
|
224 | 0 | Element value = |
225 | |
items.getChild( "Bag", NS.RDF ) |
226 | |
.getChild( "li", NS.RDF ) |
227 | |
.getChild( "item", NS.CONTENT ) |
228 | |
.getChild( "value", NS.RDF ); |
229 | |
|
230 | |
|
231 | |
|
232 | |
|
233 | 0 | mcpl.onContentItem( new FeedParserState( value ), |
234 | |
null, |
235 | |
null, |
236 | |
value ); |
237 | |
|
238 | 0 | mcpl.onContentItemEnd(); |
239 | |
|
240 | |
} |
241 | |
|
242 | |
} |
243 | |
|
244 | |
} |
245 | |
|
246 | |
|
247 | |
|
248 | 0 | if ( listener instanceof XHTMLFeedParserListener ) { |
249 | |
|
250 | 0 | XHTMLFeedParserListener xfp = (XHTMLFeedParserListener)listener; |
251 | |
|
252 | 0 | Element body = state.current.getChild( "body", NS.XHTML ); |
253 | |
|
254 | |
|
255 | |
|
256 | |
|
257 | 0 | if ( body != null ) { |
258 | 0 | xfp.onXHTMLBody( new FeedParserState( body ), |
259 | |
body ); |
260 | 0 | xfp.onXHTMLBodyEnd(); |
261 | |
} |
262 | |
|
263 | |
} |
264 | |
|
265 | 0 | MetaFeedParser.parse( listener, state ); |
266 | 0 | TagFeedParser.parse( listener, state ); |
267 | |
|
268 | 0 | doEnclosures( listener, state ); |
269 | |
|
270 | 0 | listener.onItemEnd(); |
271 | |
|
272 | 0 | } |
273 | |
|
274 | |
private static void doEnclosures( FeedParserListener listener, |
275 | |
FeedParserState state ) throws Exception { |
276 | |
|
277 | 0 | if ( listener instanceof LinkFeedParserListener == false ) |
278 | 0 | return; |
279 | |
|
280 | 0 | Element element = state.current.getChild( "enclosure" ); |
281 | |
|
282 | 0 | if ( element == null ) |
283 | 0 | return; |
284 | |
|
285 | 0 | LinkFeedParserListener linkFeedParserListener = (LinkFeedParserListener)listener; |
286 | |
|
287 | 0 | String rel = null; |
288 | 0 | String type = element.getAttributeValue( "type" ); |
289 | 0 | String href = element.getAttributeValue( "url" ); |
290 | 0 | String title = null; |
291 | 0 | long length = 0; |
292 | 0 | if (element.getAttributeValue("length") != null) |
293 | 0 | length = Integer.parseInt( element.getAttributeValue( "length" ) ); |
294 | |
|
295 | 0 | linkFeedParserListener.onLink( state, |
296 | |
rel, |
297 | |
type, |
298 | |
href, |
299 | |
title, |
300 | |
length ); |
301 | |
|
302 | 0 | } |
303 | |
|
304 | |
} |