- 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
68 lines
2.4 KiB
Kotlin
68 lines
2.4 KiB
Kotlin
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
|
|
}
|
|
}
|