Code Monkey home page Code Monkey logo

Comments (7)

yogthos avatar yogthos commented on June 15, 2024 2

great, just pushed out 0.2.6 with the fix.

from clj-rss.

yogthos avatar yogthos commented on June 15, 2024

Hmm, it looks clojure.data.xml doesn't like the uri. Could you provide what (cdata blog-image-url) ends up generating?

from clj-rss.

Sangdol avatar Sangdol commented on June 15, 2024

Thanks for the answer, Dmitri. It seems it throws an error regardless of the uri value.

I've created a branch with a reproducible code so that you can take a look.

https://github.com/Sangdol/clj-rss/blob/rss-image-tag/test/clj_rss/core_test.clj#L7

from clj-rss.

yogthos avatar yogthos commented on June 15, 2024

I added support on a branch here, this will allow providing a hint for the type of the tag using the :type key as follows:

(channel-xml {:title "Foo" :link "http://x" :description "some channel"}
             {:type  :image
              :title "image"
              :url   "http://foo.bar"
              :link  "http://bar.baz"}
             {:title "foo" :link "bar"}) 

let me know if that looks good to you

from clj-rss.

Sangdol avatar Sangdol commented on June 15, 2024

Thanks for the fix. It works well.

I just found one interesting thing that I don't understand why it's happening.

When I generate an image tag with cdata contents only the one in the url tag gets escaped. It's okay in my use case but I believe this is not the right behavior.

{:type  :image
 :url   (cdata "url")
 :title (cdata "title")
 :link  (cdata "link")}
<image>
    <url>&lt;![CDATA[ url ]]&gt;</url>
    <title><![CDATA[ title ]]></title>
    <link><![CDATA[ link ]]></link>
</image>

from clj-rss.

yogthos avatar yogthos commented on June 15, 2024

That's actually the expected behavior currently. When the tags are generated, the following function is called:

(defn- make-tags [tags]
  (flatten
    (for [[k v] (seq tags)]
      (cond
        (and (coll? v) (map? (first v)))
        (apply-macro clj-rss.core/tag (into [k] v))
        (coll? v)
        (map (fn [v] (make-tags {k v})) v)
        :else
        (tag k (cond
                 (some #{k} [:pubDate :lastBuildDate]) (format-time v)
                 (some #{k} [:description :title :link :author]) (xml-str v)
                 :else v))))))

It will call xml-str function on :description, :title, :link, and :author tags. This function looks as follows:

(defn- xml-str
  "Returns a value suitable for inclusion as an XML element. If the string
  is wrapped in <![CDATA[ ... ]]>, remove the tags and wrap in a CData record"
  [^String s]
  (if (and (.startsWith s "<![CDATA[")
           (.endsWith s "]]>"))
    (-> s
        (.replace "<![CDATA[" "")
        (.replace "]]>" "")
        cdata)
    s))

It checks if the string starts with <![CDATA[ and ends with ]]>, when that's the case the string is assumed to be a CDATA tag and it's wrapped with a call to cdata with the tags stripped. Otherwise, it will be left alone. Since you're calling cdata explicitly before passing the data in, it ends up being unprocessed and gets escaped. Since :url is not one of the keys that triggers xml-str wrapping, it's left alone and then escaped when XML is generated.

If you call channel function instead of channel-xml, you can see the intermediate structure that gets serialized to XML:

(channel
          {:title "foo" :link "http://foo" :description "bar"}
          {:type  :image
           :title "<![CDATA[ title ]]>"
           :url   "<![CDATA[ url ]]>"
           :link  "<![CDATA[ link ]]>"})

{:tag     :rss,
         :attrs   {:version "2.0", "xmlns:atom" "http://www.w3.org/2005/Atom"},
         :content [{:tag     :channel,
                    :attrs   nil,
                    :content [{:tag "atom:link", :attrs {:href "http://foo", :rel "self", :type "application/rss+xml"}}
                              {:content ["foo"], :attrs nil, :tag :title}
                              {:content ["http://foo"], :attrs nil, :tag :link}
                              {:content ["bar"], :attrs nil, :tag :description}
                              {:content ["clj-rss"], :attrs nil, :tag :generator}
                              {:tag     :image,
                               :attrs   nil,
                               :content [{:content [#clojure.data.xml.node.CData{:content " title "}], :attrs nil, :tag :title}
                                         {:content ["<![CDATA[ url ]]>"], :attrs nil, :tag :url}
                                         {:content [#clojure.data.xml.node.CData{:content " link "}], :attrs nil, :tag :link}]}]}]}

from clj-rss.

Sangdol avatar Sangdol commented on June 15, 2024

Okay, I actually didn't exactly understand that there's no difference between CDATA and escaping when the value is actually used. It looks good and you can merge the PR and close the ticket. Thanks a lot for the answers and the fix.

from clj-rss.

Related Issues (9)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.