diff --git a/README.md b/README.md
index 37b482e6..6a2e0cd3 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ Articles can have following attributes:
The library is uploaded in jCenter, so you can easily add the dependency:
```Gradle
dependencies {
- compile 'com.prof.rssparser:rssparser:2.1.0'
+ compile 'com.prof.rssparser:rssparser:2.1.1'
}
```
#### Use:
diff --git a/build.gradle b/build.gradle
index d89b1b89..3cbfa1f7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,8 +3,8 @@ apply plugin: "com.github.ben-manes.versions"
buildscript {
ext.versions = [
- 'libVersionCode' : 21000,
- 'libVersionName' : '2.1.0',
+ 'libVersionCode' : 21001,
+ 'libVersionName' : '2.1.1',
'compileSdk' : 29,
'minSdk' : 14,
'targetSdk' : 29,
diff --git a/rssparser/build.gradle b/rssparser/build.gradle
index 5f24e483..edde83f2 100644
--- a/rssparser/build.gradle
+++ b/rssparser/build.gradle
@@ -9,8 +9,8 @@ android {
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
- versionCode 21000
- versionName "2.1.0"
+ versionCode 21001
+ versionName "2.1.1"
}
buildTypes {
diff --git a/rssparser/src/main/java/com/prof/rssparser/Image.kt b/rssparser/src/main/java/com/prof/rssparser/Image.kt
index 894bf780..108978a4 100644
--- a/rssparser/src/main/java/com/prof/rssparser/Image.kt
+++ b/rssparser/src/main/java/com/prof/rssparser/Image.kt
@@ -3,5 +3,6 @@ package com.prof.rssparser
data class Image(
var title: String? = null,
var url: String? = null,
- var link: String? = null
+ var link: String? = null,
+ var description: String? = null
)
\ No newline at end of file
diff --git a/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt b/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt
index 5458e6bd..7ef6375a 100644
--- a/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt
+++ b/rssparser/src/main/java/com/prof/rssparser/core/CoreXMLParser.kt
@@ -17,7 +17,6 @@
package com.prof.rssparser.core
-import android.util.Log
import com.prof.rssparser.Article
import com.prof.rssparser.Channel
import com.prof.rssparser.Image
@@ -62,32 +61,42 @@ object CoreXMLParser {
if (eventType == XmlPullParser.START_TAG) {
if (xmlPullParser.name.equals(RSSKeywords.RSS_CHANNEL, ignoreCase = true)) {
insideChannel = true
- insideItem = false
- insideChannelImage = false
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM, ignoreCase = true)) {
insideItem = true
- insideChannel = false
- insideChannelImage = false
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_CHANNEL_IMAGE, ignoreCase = true)) {
- insideItem = false
- insideChannel = false
insideChannelImage = true
channelImage = Image()
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_TITLE, ignoreCase = true)) {
- when {
- insideChannel -> channelTitle = xmlPullParser.nextText().trim()
- insideChannelImage -> channelImage?.title = xmlPullParser.nextText().trim()
- insideItem -> currentArticle.title = xmlPullParser.nextText().trim()
+ if (insideChannel) {
+ when {
+ insideChannelImage -> {
+ channelImage?.title = xmlPullParser.nextText().trim()
+ }
+ insideItem -> {
+ currentArticle.title = xmlPullParser.nextText().trim()
+ }
+ else -> {
+ channelTitle = xmlPullParser.nextText().trim()
+ }
+ }
}
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_LINK, ignoreCase = true)) {
- when {
- insideChannel -> channelLink = xmlPullParser.nextText().trim()
- insideChannelImage -> channelImage?.link = xmlPullParser.nextText().trim()
- insideItem -> currentArticle.link = xmlPullParser.nextText().trim()
+ if (insideChannel) {
+ when {
+ insideChannelImage -> {
+ channelImage?.link = xmlPullParser.nextText().trim()
+ }
+ insideItem -> {
+ currentArticle.link = xmlPullParser.nextText().trim()
+ }
+ else -> {
+ channelLink = xmlPullParser.nextText().trim()
+ }
+ }
}
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_AUTHOR, ignoreCase = true)) {
@@ -108,88 +117,103 @@ object CoreXMLParser {
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_URL, ignoreCase = true)) {
if (insideChannelImage) {
channelImage?.url = xmlPullParser.nextText().trim()
- Log.d("PARSER", "")
}
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_ENCLOSURE, ignoreCase = true)) {
if (insideItem) {
val type = xmlPullParser.getAttributeValue(null, RSSKeywords.RSS_ITEM_TYPE)
- if (type != null && type.contains("image/")) {
+ if (type != null && type.contains("image")) {
currentArticle.image = xmlPullParser.getAttributeValue(null, RSSKeywords.RSS_ITEM_URL)
+ } else {
+ // let's try if there is the url
+ val url = xmlPullParser.getAttributeValue(null, RSSKeywords.RSS_ITEM_URL)
+ if (url != null) {
+ currentArticle.image = url
+ }
}
}
} else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_DESCRIPTION, ignoreCase = true)) {
if (insideChannel) {
- channelDescription = xmlPullParser.nextText().trim()
- } else if (insideItem) {
- val description = xmlPullParser.nextText()
- currentArticle.description = description.trim()
- if (currentArticle.image == null) {
- currentArticle.image = getImageUrl(description)
- }
- }
-
- } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_CONTENT, ignoreCase = true)) {
- if (insideItem) {
- val content = xmlPullParser.nextText().trim()
- currentArticle.content = content
- if (currentArticle.image == null) {
- currentArticle.image = getImageUrl(content)
+ if (insideItem) {
+ val description = xmlPullParser.nextText()
+ currentArticle.description = description.trim()
+ if (currentArticle.image == null) {
+ currentArticle.image = getImageUrl(description)
+ }
+ } else if (insideChannelImage) {
+ channelImage?.description = xmlPullParser.nextText().trim()
+ } else {
+ channelDescription = xmlPullParser.nextText().trim()
}
}
- } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_PUB_DATE, ignoreCase = true)) {
- if (insideItem) {
- val nextTokenType = xmlPullParser.next()
- if (nextTokenType == XmlPullParser.TEXT) {
- currentArticle.pubDate = xmlPullParser.text.trim()
- }
- // Skip to be able to find date inside 'tag' tag
- continue
+ } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_CONTENT, ignoreCase = true)) {
+ if (insideItem) {
+ val content = xmlPullParser.nextText().trim()
+ currentArticle.content = content
+ if (currentArticle.image == null) {
+ currentArticle.image = getImageUrl(content)
}
+ }
- } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_TIME, ignoreCase = true)) {
- if (insideItem) {
- currentArticle.pubDate = xmlPullParser.nextText()
+ } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_PUB_DATE, ignoreCase = true)) {
+ if (insideItem) {
+ val nextTokenType = xmlPullParser.next()
+ if (nextTokenType == XmlPullParser.TEXT) {
+ currentArticle.pubDate = xmlPullParser.text.trim()
}
+ // Skip to be able to find date inside 'tag' tag
+ continue
+ }
- } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_GUID, ignoreCase = true)) {
- if (insideItem) {
- currentArticle.guid = xmlPullParser.nextText().trim()
- }
+ } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_TIME, ignoreCase = true)) {
+ if (insideItem) {
+ currentArticle.pubDate = xmlPullParser.nextText()
}
- } else if (eventType == XmlPullParser.END_TAG && xmlPullParser.name.equals("item", ignoreCase = true)) {
- // The item is correctly parsed
- insideItem = false
- articleList.add(currentArticle)
- currentArticle = Article()
+ } else if (xmlPullParser.name.equals(RSSKeywords.RSS_ITEM_GUID, ignoreCase = true)) {
+ if (insideItem) {
+ currentArticle.guid = xmlPullParser.nextText().trim()
+ }
}
- eventType = xmlPullParser.next()
+
+ } else if (eventType == XmlPullParser.END_TAG && xmlPullParser.name.equals(RSSKeywords.RSS_ITEM, ignoreCase = true)) {
+ // The item is correctly parsed
+ insideItem = false
+ articleList.add(currentArticle)
+ currentArticle = Article()
+ } else if (eventType == XmlPullParser.END_TAG && xmlPullParser.name.equals(RSSKeywords.RSS_CHANNEL, ignoreCase = true)) {
+ // The channel is correctly parsed
+ insideChannel = false
+ } else if (eventType == XmlPullParser.END_TAG && xmlPullParser.name.equals(RSSKeywords.RSS_CHANNEL_IMAGE, ignoreCase = true)) {
+ // The channel image is correctly parsed
+ insideChannelImage = false
}
- return Channel(channelTitle, channelLink, channelDescription, channelImage, articleList)
+ eventType = xmlPullParser.next()
}
+ return Channel(channelTitle, channelLink, channelDescription, channelImage, articleList)
+}
- /**
- * Finds the first img tag and get the src as featured image
- *
- * @param input The content in which to search for the tag
- * @return The url, if there is one
- */
- private fun getImageUrl(input: String): String? {
-
- var url: String? = null
- val patternImg = Pattern.compile("()")
- val matcherImg = patternImg.matcher(input)
- if (matcherImg.find()) {
- val imgTag = matcherImg.group(1)
- val patternLink = Pattern.compile("src\\s*=\\s*\"(.+?)\"")
- val matcherLink = patternLink.matcher(imgTag)
- if (matcherLink.find()) {
- url = matcherLink.group(1).trim()
- }
+/**
+ * Finds the first img tag and get the src as featured image
+ *
+ * @param input The content in which to search for the tag
+ * @return The url, if there is one
+ */
+private fun getImageUrl(input: String): String? {
+
+ var url: String? = null
+ val patternImg = Pattern.compile("()")
+ val matcherImg = patternImg.matcher(input)
+ if (matcherImg.find()) {
+ val imgTag = matcherImg.group(1)
+ val patternLink = Pattern.compile("src\\s*=\\s*\"(.+?)\"")
+ val matcherLink = patternLink.matcher(imgTag)
+ if (matcherLink.find()) {
+ url = matcherLink.group(1).trim()
}
- return url
}
+ return url
+}
}
diff --git a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImage2FeedTest.kt b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImage2FeedTest.kt
index 84bd75e2..d84e7090 100644
--- a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImage2FeedTest.kt
+++ b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImage2FeedTest.kt
@@ -76,6 +76,11 @@ class CoreXMLParserImage2FeedTest {
assertEquals(channel.image?.url, "https://www.mundodeportivo.com/rsc/images/logo_MD_feed.png")
}
+ @Test
+ fun channelImageDescription_isCorrect() {
+ assertEquals(channel.image?.description, "Mundo Deportivo es tu diario deportivo On Line. Noticias de deporte, fútbol y del Barça")
+ }
+
@Test
@Throws
fun size_isCorrect() {
diff --git a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageChannelReverseTest.kt b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageChannelReverseTest.kt
new file mode 100644
index 00000000..fefb867a
--- /dev/null
+++ b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageChannelReverseTest.kt
@@ -0,0 +1,126 @@
+package com.prof18.rssparser
+
+import android.os.Build
+import com.prof.rssparser.Article
+import com.prof.rssparser.Channel
+import com.prof.rssparser.core.CoreXMLParser
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+
+@RunWith(RobolectricTestRunner::class)
+@Config(sdk = [Build.VERSION_CODES.P])
+class CoreXMLParserImageChannelReverseTest {
+ private lateinit var articleList: MutableList
+ private lateinit var article: Article
+ private val feedPath = "/feed-test-image-channel-reverse.xml"
+ private lateinit var channel: Channel
+
+ @Before
+ fun setUp() {
+ val inputStream = javaClass.getResourceAsStream(feedPath)!!
+ val feed = inputStream.bufferedReader().use { it.readText() }
+ channel = CoreXMLParser.parseXML(feed)
+ articleList = channel.articles
+ article = articleList[0]
+ }
+
+ @Test
+ fun channelTitle_isCorrect() {
+ Assert.assertEquals(channel.title, "The Joe Rogan Experience")
+ }
+
+ @Test
+ fun channelDesc_isCorrect() {
+ Assert.assertEquals(channel.description, "The podcast of Comedian Joe Rogan..")
+ }
+
+ @Test
+ fun channelLink_isCorrect() {
+ Assert.assertEquals(channel.link, "https://www.joerogan.com")
+ }
+
+ @Test
+ fun channelImageTitle_isCorrect() {
+ Assert.assertEquals(channel.image?.title, "The Joe Rogan Experience")
+ }
+
+ @Test
+ fun channelImageLink_isCorrect() {
+ Assert.assertEquals(channel.image?.link, "https://www.joerogan.com")
+ }
+
+ @Test
+ fun channelImageUrl_isCorrect() {
+ Assert.assertEquals(channel.image?.url, "http://static.libsyn.com/p/assets/7/1/f/3/71f3014e14ef2722/JREiTunesImage2.jpg")
+ }
+
+ @Test
+ fun channelImageDescription_isCorrect() {
+ Assert.assertNull(channel.image?.description)
+ }
+
+ @Test
+ @Throws
+ fun size_isCorrect() {
+ Assert.assertEquals(articleList.size, 6)
+ }
+
+
+ @Test
+ @Throws
+ fun title_isCorrect() {
+ Assert.assertEquals(article.title, "#1405 - Sober October 3 Recap")
+ }
+
+ @Test
+ @Throws
+ fun author_isCorrect() {
+ Assert.assertEquals(article.author, null)
+ }
+
+ @Test
+ @Throws
+ fun link_isCorrect() {
+ Assert.assertEquals(article.link, "http://traffic.libsyn.com/joeroganexp/p1405.mp3")
+ }
+
+ @Test
+ @Throws
+ fun pubDate_isCorrect() {
+ Assert.assertEquals(article.pubDate, "Tue, 24 Dec 2019 20:00:00 +0000")
+ }
+
+ @Test
+ @Throws
+ fun description_isPresent() {
+ Assert.assertEquals(article.description, "Joe is joined by Ari Shaffir, Bert Kreischer & Tom Segura to recap their 3rd annual Sober October challenge.")
+ }
+
+ @Test
+ @Throws
+ fun content_isCorrect() {
+ Assert.assertEquals(article.content, "Joe is joined by Ari Shaffir, Bert Kreischer & Tom Segura to recap their 3rd annual Sober October challenge.")
+ }
+
+ @Test
+ @Throws
+ fun image_isCorrect() {
+ Assert.assertEquals(article.image, "http://traffic.libsyn.com/joeroganexp/p1405.mp3?dest-id=19997")
+ }
+
+ @Test
+ @Throws
+ fun categories_isCorrect() {
+ assert(article.categories.isEmpty())
+ }
+
+ @Test
+ @Throws
+ fun guid_isCorrect() {
+ Assert.assertEquals(article.guid, "0d7147a3-f1c1-4ae6-bbf8-2e0a493639ca")
+ }
+}
\ No newline at end of file
diff --git a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageFeedTest.kt b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageFeedTest.kt
index 3bdfe356..9d4a6dcf 100644
--- a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageFeedTest.kt
+++ b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserImageFeedTest.kt
@@ -21,6 +21,7 @@ import android.os.Build
import com.prof.rssparser.Article
import com.prof.rssparser.Channel
import com.prof.rssparser.core.CoreXMLParser
+import org.junit.Assert
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
@@ -75,6 +76,11 @@ class CoreXMLParserImageFeedTest {
assertEquals(channel.image?.url, "https://cdn.movieweb.com/assets/1/sites/movieweb.com/chrome-touch-icon-192x192.png")
}
+ @Test
+ fun channelImageDescription_isCorrect() {
+ assertNull(channel.image?.description)
+ }
+
@Test
@Throws
fun size_isCorrect() {
diff --git a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserXSLFeedTest.kt b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserXSLFeedTest.kt
index 413111aa..06a1b393 100644
--- a/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserXSLFeedTest.kt
+++ b/rssparser/src/test/java/com/prof18/rssparser/CoreXMLParserXSLFeedTest.kt
@@ -21,6 +21,7 @@ import android.os.Build
import com.prof.rssparser.Article
import com.prof.rssparser.Channel
import com.prof.rssparser.core.CoreXMLParser
+import org.junit.Assert
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
@@ -75,6 +76,11 @@ class CoreXMLParserXSLFeedTest {
assertEquals(channel.image?.url, "https://www.skysports.com/images/site/ss-logo-07.gif")
}
+ @Test
+ fun channelImageDescription_isCorrect() {
+ assertNull(channel.image?.description)
+ }
+
@Test
@Throws
fun size_isCorrect() {
diff --git a/rssparser/src/test/resources/feed-test-image-channel-reverse.xml b/rssparser/src/test/resources/feed-test-image-channel-reverse.xml
new file mode 100644
index 00000000..db6f2183
--- /dev/null
+++ b/rssparser/src/test/resources/feed-test-image-channel-reverse.xml
@@ -0,0 +1,135 @@
+
+
+
+
+ The Joe Rogan Experience
+ Tue, 24 Dec 2019 20:00:00 +0000
+ Sat, 04 Jan 2020 01:06:48 +0000
+ Libsyn WebEngine 2.0
+ https://www.joerogan.com
+ en
+
+ https://www.joerogan.com
+ joe@joerogan.net (joe@joerogan.net)
+
+
+ http://static.libsyn.com/p/assets/7/1/f/3/71f3014e14ef2722/JREiTunesImage2.jpg
+ The Joe Rogan Experience
+
+
+ Joe Rogan
+ comedian,joe,monkey,redban,rogan,talking,ufc
+
+
+
+
+
+
+ yes
+
+
+ joe@joerogan.net
+
+
+
+ episodic
+
+ http://joeroganexp.joerogan.libsynpro.com/rss
+ -
+ #1405 - Sober October 3 Recap
+ Tue, 24 Dec 2019 20:00:00 +0000
+
+
+
+
+
+
+ 03:30:48
+ no
+ podcast,3,joe,party,experience,tom,ari,october,bert,freak,rogan,recap,sober,kreischer,shaffir,segura,deathsquad,jre,1405
+
+ 1405
+ full
+
+ -
+ #1404 - Bryan Callen
+ Sat, 21 Dec 2019 05:00:00 +0000
+
+
+
+
+
+
+ 03:08:16
+ no
+ podcast,joe,party,experience,bryan,freak,rogan,callen,deathsquad,jre,1404
+
+ 1404
+ full
+
+ -
+ #1403 - Forrest Galante
+ Thu, 19 Dec 2019 20:00:00 +0000
+
+
+
+
+
+
+ 02:56:30
+ no
+ podcast,joe,forrest,party,experience,freak,rogan,galante,deathsquad,jre,1403
+
+ 1403
+ full
+
+ -
+ JRE MMA Show #85 with Max Holloway
+ Wed, 18 Dec 2019 20:00:00 +0000
+
+
+
+
+
+
+ 02:13:41
+ no
+ podcast,mma,show,joe,party,experience,max,holloway,freak,rogan,85,deathsquad
+
+ 1402
+ full
+
+ -
+ #1402 - Boyan Slat
+ Tue, 17 Dec 2019 20:00:00 +0000
+
+
+
+
+
+
+ 01:54:00
+ no
+ podcast,joe,party,experience,freak,rogan,1402,deathsquad,slat,jre,boyan
+
+ 1402
+ full
+
+ -
+ #1401 - Iliza Shlesinger
+ Tue, 17 Dec 2019 04:00:00 +0000
+
+
+
+
+
+
+ 02:35:30
+ no
+ podcast,joe,party,experience,freak,rogan,iliza,deathsquad,jre,shlesinger,1401
+
+ 1401
+ full
+
+
+
\ No newline at end of file