bhylu.com

Advertisements

XML RSS Feeds

An RSS feed publishes a channel and a sequence of items. A small XML parser can read update titles, but a feed consumer still needs a trust and rendering policy.

How it works

RSS 2.0 uses rss as its root with version="2.0" and a channel containing metadata. An item can include a title, link and other fields; guid identifies an item and is not always a URL. This original fixture publishes one seed-exchange update and uses a reserved example domain for links. Feed descriptions from unknown publishers may contain markup, so display safe text or apply a deliberately chosen sanitization policy.

Run the code

Use Python 3 with lxml 6.1.1 in a separate virtual environment. The complete listing embeds its own XML and any schema or stylesheet; run python rss-feed.py. It does not need Apache or MySQL. The shared restrictive parse function rejects declarations for untrusted input. The trusted DTD/entity and streaming lessons explicitly explain their separate fixed-input boundaries.

Download the complete rss-feed.py source. Keep each lab in its own folder. Sources are served as text, not as public executable server scripts. Review the starting setup.

Example

rss-feed.py

from lxml import etree as E

class DenyExternal(E.Resolver):
    def resolve(self, url, public_id, context):
        raise ValueError("External resources are disabled")

def parse(text):
    if "<!DOCTYPE" in text.upper() or "<!ENTITY" in text.upper():
        raise ValueError("Declarations are disabled for untrusted XML")
    parser = E.XMLParser(resolve_entities=False, load_dtd=False,
                         no_network=True, huge_tree=False)
    parser.resolvers.add(DenyExternal())
    return E.fromstring(text.encode("utf-8"), parser)

source = "<rss version=\"2.0\"><channel><title>Seed circle updates</title><link>https://example.test/seeds</link><description>Local exchange notices</description><item><title>Marigold packets returned</title><link>https://example.test/seeds/p1</link><guid isPermaLink=\"false\">seed-update-001</guid></item></channel></rss>"
root = parse(source)
print(root.xpath("string(channel/title)"))
print(root.xpath("string(channel/item/guid)"))

Expected result

Seed circle updates
seed-update-001

The channel title describes the feed and the item guid provides stable identity. This example reads a fixed feed offline; it does not submit a feed to a platform or prove every RSS extension is supported.

Check the exact contract in the XML specification, XPath 1.0, the XSD 1.0 primer, lxml validation documentation and Saxon’s processor documentation.