arnab gupta

Octopress—adding category tags to the blog RSS feed

May 28, 2016

Right from the beginning, I’ve assigned broad categories to every post I’ve written here. (For example, this is my—very lacking—Health Monitoring series of posts.) However, Octopress does not include these category tags by default into the RSS feed. So if a reader is using an RSS feed-reader app or website, they cannot make use of the assigned categories even if the app or website was capable of doing so.

I’ve now added some code necessary to add the categories to the RSS feed, and this is what I did.

At the outset, here is the code that I added:

Add tags to RSS feed (addtagcode.xml) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% for post in site.posts limit: 20 %}
    <entry>
    <!-- Other items that are included in the feed -->

    {% capture catnum %}{{ post.categories | category_links | size }}{% endcapture %}
    {% unless catnum == '0' %}
        <categories>
        {% for cct in post.categories %}
            {% assign idx=forloop.index0 %}<category>{{ post.categories[idx] }}</category>
        {% endfor %}
        </categories>
    {% endunless %}

    <!-- Other items that are included in the feed -->
    <content type="html"><![CDATA[{{ post.content | expand_urls: site.url | cdata_escape }}]]></content>
    </entry>
{% endfor %}

This code works great, but allow me to confess that I am not sure that this is the optimum implementation. To me this seems inelegant, but until I have a better solution, this performs the function appropriately and perfectly adequately.

I’ve only included the relevant portion and the context in which it must be inserted. (See the comment tags <!-- Other items that are included in the feed -->.)

The meat of the algorithm is from lines 7 through 11.

  • A <categories> tag is defined, and a for loop is executed over post.categories, which contains the list of categories for the post.
  • Within the for loop, each post category is enclosed in a <category></category> tag.

Now I had initially thought that the loop variable (cct here) would inherit sequentially the value of each category in post.categories, but apparently that does not work properly. Therefore, the workaround is to

  • identify the loop index (assign idx=forloop.index0) and
  • use individual values of the categories (post.categories[idx]).

We must use forloop.index0 and NOT forloop.index (both are valid commands; the index key starts numbering from 1) because the array numbering starts from 0, not 1.

OK, now that the meat of the algorithm is done, we must put in some code to handle the “unusual” cases—what happens if a post does not have any categories assigned? Such a scenario is handled by the capture command (line 5) and the unless segment that encloses our actual algorithm. The capture command simply captures a value, in our case the number of categories that exist. We only want to include the categories when they exist, therefore our algorithm is run only unless catnum=='0' i.e. when the number of categories is not 0.

Well, that’s it! I have added the code segment before the actual content of each post, but I don’t think it makes any difference if the segment appears after the <content> tag. It should work fine anywhere within the <entry> environment.