Search code examples
validationgrailsgroovyrssfeed

Grails feeds-Plugin, <pubDate> && <dc:date>, validation error


I just tried out the grails feeds-plugin http://grails.org/Feeds+Plugin

It works very easy and well, but there´s one thing I don´t understand.

As soon as I add a publishedDate, like:

     reviews.each() {
         review -> entry('fooTitle'){
             publishedDate = review.dtCreated
             review.rating + ' ' + review.comment
        }
     }

It generates two tags:

      <pubDate>Tue, 04 Sep 2012 12:10:02 GMT</pubDate>
      <dc:date>2012-09-04T12:10:02Z</dc:date>

The entry in Database is:

"dtCreated": ISODate("2013-01-15T00:52:47.0Z"),

but I only want the <pubDate> to be generated, because feed validator throws this error:

An item should not include both pubDate and dc:date 

How can I solve this? I would love to use this plugin but I need a valid RSS.


Solution

  • If you don't mind a quick and dirty solution you can try this (it's taken from plugin's integration tests and modified):

    import groovy.xml.XmlUtil
    import groovy.xml.StreamingMarkupBuilder
    import feedsplugin.FeedBuilder
    import com.sun.syndication.io.SyndFeedOutput
    
    class TestController {
    private renderToString(feedType, feedVersion, Closure closure) {
        def builder = new FeedBuilder()
        builder.feed(closure)
    
        def type = feedType
        def version = feedVersion
    
        SyndFeedOutput output = new SyndFeedOutput()
        def sw = new StringWriter()
        output.output(builder.makeFeed(type, version),sw)
        sw.toString()
    
    }
    
    private removeDcDate(String rssFeed) {
    
        def dom = new XmlSlurper().parseText(rssFeed)
        dom.channel[0].item.eachWithIndex { item, i ->
            dom.channel[0].item[i].date = {}
        }
    
        def newResp = XmlUtil.serialize(new StreamingMarkupBuilder().bind {
            mkp.declareNamespace (rdf:"http://www.w3.org/1999/02/22-rdf-syntax-ns#")
            mkp.declareNamespace (dc:"http://purl.org/dc/elements/1.1/")
            mkp.declareNamespace (content:"http://purl.org/rss/1.0/modules/content/")
            mkp.declareNamespace (itunes:"http://www.itunes.com/dtds/podcast-1.0.dtd")
            mkp.declareNamespace (taxo:"http://purl.org/rss/1.0/modules/taxonomy/")
    
            mkp.yield dom 
        })
    
        newResp
    
    }
    
    def test = {
        def articles = ['A', 'B', 'C']
    
         def outStr= renderToString("rss", "2.0") {
            title = 'Test feed'
            link = 'http://somewhere.com/'
            description = "This is a test feed" 
    
            articles.each() { article ->
                entry("Title for \$article") {
                    content(type:'text/html') {
                        return "Content for \$article"
                    }
    
                    link = 'http://somewhere.com/x'
    
                    publishedDate = new Date()
    
                }
            }
        }
        def cleanedFeed = removeDcDate(outStr)
    
        render text: cleanedFeed, contentType: "application/rss+xml", encoding: "UTF-8"
    
        }
    }
    

    Basically what it does is calling feedbuilder directly to get a string representation of the feed, then it get parsed it and the "dc:date" tags are deleted. The result is rendered as usual.

    I've tested this workaround inside the plugin test suite with grails 1.3.7