Implement Android RSS/Atom feed parser
- Add FeedParser.kt with automatic feed type detection - Add RSSParser.kt for RSS 2.0 feeds - Add AtomParser.kt for Atom 1.0 feeds - Add comprehensive unit tests for both parsers - Support iTunes namespace and enclosures - Fix pre-existing compilation issues in the codebase - Update build.gradle.kts with proper dependencies and AGP 8.5.0
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package com.rssuper.parsing
|
||||
|
||||
import com.rssuper.models.Feed
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserFactory
|
||||
import java.io.StringReader
|
||||
import java.util.Date
|
||||
|
||||
object FeedParser {
|
||||
|
||||
fun parse(xml: String, feedUrl: String): ParseResult {
|
||||
val feedType = detectFeedType(xml)
|
||||
|
||||
return when (feedType) {
|
||||
FeedType.RSS -> {
|
||||
val feed = RSSParser.parse(xml, feedUrl)
|
||||
ParseResult(FeedType.RSS, feed)
|
||||
}
|
||||
FeedType.Atom -> {
|
||||
val feed = AtomParser.parse(xml, feedUrl)
|
||||
ParseResult(FeedType.Atom, feed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun parseAsync(xml: String, feedUrl: String, callback: (Result<ParseResult>) -> Unit) {
|
||||
try {
|
||||
val result = parse(xml, feedUrl)
|
||||
callback(Result.success(result))
|
||||
} catch (e: Exception) {
|
||||
callback(Result.failure(e))
|
||||
}
|
||||
}
|
||||
|
||||
private fun detectFeedType(xml: String): FeedType {
|
||||
val factory = XmlPullParserFactory.newInstance()
|
||||
factory.isNamespaceAware = true
|
||||
val parser = factory.newPullParser()
|
||||
parser.setInput(StringReader(xml))
|
||||
|
||||
var eventType = parser.eventType
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
val tagName = parser.name
|
||||
return when {
|
||||
tagName.equals("rss", ignoreCase = true) -> FeedType.RSS
|
||||
tagName.equals("feed", ignoreCase = true) -> FeedType.Atom
|
||||
tagName.equals("RDF", ignoreCase = true) -> FeedType.RSS
|
||||
else -> {
|
||||
val namespace = parser.namespace
|
||||
if (namespace != null && namespace.isNotEmpty()) {
|
||||
when {
|
||||
tagName.equals("rss", ignoreCase = true) -> FeedType.RSS
|
||||
tagName.equals("feed", ignoreCase = true) -> FeedType.Atom
|
||||
else -> throw FeedParsingError.UnsupportedFeedType
|
||||
}
|
||||
} else {
|
||||
throw FeedParsingError.UnsupportedFeedType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
eventType = parser.next()
|
||||
}
|
||||
throw FeedParsingError.UnsupportedFeedType
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user