1

I am trying to parse an RSS feed element returned by org-feed-parse-rss-feed with a custom version of org-feed-parse-rss-entry.

(defun aleneum/org-feed-parse-rss-entry (entry)
  "Parse the `:item-full-text' field for xml tags and create new properties."
  (with-temp-buffer
    (insert (plist-get entry :item-full-text))
    (goto-char (point-min))
    (while (re-search-forward "<\\([a-zA-Z]+\\>\\).*?>\\([^\000]*?\\)</\\1>"
                  nil t)
      (setq entry (plist-put entry
                 (intern (concat ":" (match-string 1)))
                 (xml-substitute-special (match-string 2)))))
    (goto-char (point-min))
    (unless (re-search-forward "isPermaLink[ \t]*=[ \t]*\"false\"" nil t)
      (setq entry (plist-put entry :guid-permalink t)))
    (setq entry (plist-put entry :title (concat "TODO " (plist-get entry :title))))
    )
  entry)

Currently, my addition is rather small and only adds TODO to each RSS entry. My problem is that basically all the content in the parsed RSS feed is HTML and wrapped into CDATA sections. Parsed entries look like this:

* TODO <![CDATA[A title]]>
  2022-04-25 Mon 02:26
  <![CDATA[<p>A paragraph</p>
This is the <pre>HTML</pre> content of this rss entry.
]]>

How can I convert this to 'plain' text? Or more precisely: How can I get rid of the CDATA annotation and also strip HTML tags from the content?

1

1 Answer 1

0

I found a solution that worked for me (as of now). My goal was to convert RSS entries of a Github issue feed (provided by https://rsshub.app) into TODO items. First, I extended the regular expression that converts tags into ':param'/content pairs to strip CDATA prefixes and suffixes and feed the content of :description to a pandoc helper function found here to convert the HTML content into org-mode notation:


(defun pandoc-convert-stdio (body input-format output-format)
  "Convert `BODY' as `INPUT-FORMAT' to `OUTPUT-FORMAT'."
  (let ((args (list "-f" input-format "-t" output-format)))
    (with-temp-buffer
      (insert body)
      (apply 'call-process-region (point-min) (point-max) "pandoc" t t nil args)
      (buffer-substring-no-properties (point-min) (point-max)))))


(defun aleneum/org-feed-parse-github-entry (entry)
  "Parse the `:item-full-text' field for xml tags and create new properties."
  (with-temp-buffer
    (insert (plist-get entry :item-full-text))
    (goto-char (point-min))
    (while (re-search-forward "<\\([a-zA-Z]+\\>\\).*?>\\(<!\\[CDATA\\[\\)?\\([^\000]*?\\)\\(\\]\\]>\\)?</\\1>"
                  nil t)
      (setq entry (plist-put entry
                 (intern (concat ":" (match-string 1)))
                 (xml-substitute-special (match-string 3)))))
    (goto-char (point-min))
    (unless (re-search-forward "isPermaLink[ \t]*=[ \t]*\"false\"" nil t)
      (setq entry (plist-put entry :guid-permalink t)))
    (setq entry (plist-put entry :title (concat "TODO " (plist-get entry :title))))
    (setq entry (plist-put entry :description (pandoc-convert-stdio (plist-get entry :description) "html" "org")))
    )
  entry)

I know there are at least two packages (org-sync, org-github-issues) to communicate with Github via their API but since I already consume Gitlab issues via RSS I wanted to keep the general procedure comparable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.