bx-rss
bx-rss: RSS / Atom Feed Processing
Installation
install-bx-module bx-rss
# CommandBox
box install bx-rss
Supported Formats
- RSS 2.0
- RSS 1.0 (RDF)
- Atom
- iTunes Podcast extensions
- Media RSS extensions
BIF: rss()
// Fetch and parse a feed
feed = rss( "https://blog.example.com/feed.rss" )
// Access channel metadata
writeOutput( "Title: " & feed.channel.title )
writeOutput( "Link: " & feed.channel.link )
writeOutput( "Description: " & feed.channel.description )
// Access items (array)
for ( var item of feed.items ) {
writeOutput( item.title & " — " & item.publishedDate )
writeOutput( item.link )
writeOutput( item.description )
}
Component: bx:feed — Reading
// Script syntax
bx:feed action="read" source="https://blog.example.com/feed.rss" result="feed" {
}
// Tag syntax
bx:feed action="read" source="https://blog.example.com/feed.rss" result="feed"
// With limit and filtering
bx:feed
action="read"
source="https://news.example.com/rss.xml"
result="feed"
maxItems=10
filter="boxlang"
// From local file
bx:feed action="read" source="/app/data/cached-feed.xml" result="feed"
Component: bx:feed — Creating
// Create an RSS 2.0 feed
bx:feed action="create" result="feedXml" type="rss" {
// Channel metadata passed via attributes of bx:feed or as nested struct
}
// Programmatic creation
var feedDefinition = {
type : "rss",
version : "2.0",
title : "My Blog",
link : "https://blog.example.com",
description : "Latest posts from My Blog",
xmlUrl : "https://blog.example.com/feed.rss",
items : []
}
// Add items
for ( var post of posts ) {
arrayAppend( feedDefinition.items, {
title : post.title,
link : "https://blog.example.com/post/" & post.slug,
description : post.summary,
publishedDate : post.publishedAt,
author : post.authorEmail,
guid : "https://blog.example.com/post/" & post.slug,
categories : [ post.category ]
})
}
bx:feed action="create" result="feedXml" {
// Set structure via variables.feedDefinition
}
// Write to file
fileWrite( "/app/public/feed.rss", feedXml )
// Or stream to browser
content type="application/rss+xml"
writeOutput( feedXml )
Atom Feed Creation
var feedDefinition = {
type : "atom",
version : "1.0",
title : "My Blog (Atom)",
link : "https://blog.example.com",
xmlUrl : "https://blog.example.com/atom.xml",
description : "Latest posts",
items : []
}
iTunes Podcast Feed
var feedDefinition = {
type : "rss",
version : "2.0",
title : "My Podcast",
link : "https://mypodcast.com",
description : "Weekly tech discussions",
// iTunes-specific
itunes : {
author : "Jane Doe",
image : "https://mypodcast.com/cover.jpg",
category : "Technology",
explicit : "no",
owner : { name: "Jane Doe", email: "jane@mypodcast.com" }
},
items : [
{
title : "Episode 42: BoxLang Deep Dive",
description : "We talk about BoxLang internals",
enclosure : {
url : "https://mypodcast.com/ep42.mp3",
type : "audio/mpeg",
length : 52428800
},
publishedDate : "2025-01-15",
guid : "podcast-ep-42",
itunes : {
duration : "54:22",
episode : 42
}
}
]
}
Feed Aggregator Pattern
function aggregateFeeds( feedUrls, maxPerFeed ) {
var allItems = []
for ( var url of feedUrls ) {
try {
bx:feed action="read" source=url result="feed" maxItems=maxPerFeed
for ( var item of feed.items ) {
item.source = feed.channel.title
arrayAppend( allItems, item )
}
} catch ( any e ) {
// Skip broken feeds
}
}
// Sort by date, newest first
allItems.sort( ( a, b ) -> {
return dateCompare( b.publishedDate, a.publishedDate )
})
return allItems
}
Output Feed as RSS Endpoint
// In a web handler (ColdBox or simple template)
function feed( event, rc, prc ) {
var posts = postService.getLatestPosts( 20 )
var feedData = {
channel : {
title : "My Blog",
link : event.getHTTPBasePath(),
description : "Latest posts"
},
items : posts.map( ( p ) => ({
title : p.title,
link : event.buildLink( "blog.post.#p.slug#" ),
description : p.excerpt,
publishedDate : p.publishedAt,
guid : p.id
}))
}
bx:feed action="create" result="prc.feedXml" feedProperties=feedData
event.renderData( type: "plain", data: prc.feedXml )
.setHTTPHeader( name: "Content-Type", value: "application/rss+xml; charset=utf-8" )
}
Common Pitfalls
- ✅ Always wrap feed reads in try/catch — remote URLs can fail or be malformed
- ❌ Don't assume
publishedDateis always populated — some feeds omit it - ✅ Use
maxItemsto limit memory usage when parsing large feeds - ❌ Don't hot-load live feeds on every request — cache feed results to avoid rate limits and latency
- ✅ Set
Content-Type: application/rss+xmlwhen serving feeds to browsers/RSS readers
More from ortus-boxlang/skills
boxlang-functional-programming
Use this skill when working with BoxLang lambdas, closures, arrow functions, higher-order functions, functional array/struct pipelines (map, filter, reduce, flatMap, groupBy, etc.), destructuring, or spread syntax.
10boxlang-code-reviewer
Use this skill when reviewing BoxLang code for quality, correctness, security vulnerabilities, performance issues, style violations, or when providing structured code review feedback following BoxLang best practices and security guidelines.
9boxlang-best-practices
Use this skill when writing, reviewing, or improving BoxLang code to ensure it follows community best practices for naming, structure, scoping, error handling, performance, and maintainability.
9boxlang-classes-and-oop
Use this skill when writing BoxLang classes, components, interfaces, inheritance hierarchies, annotations, properties, constructors, or applying object-oriented design patterns in BoxLang.
9boxlang-web-development
Use this skill when building BoxLang web applications: Application.bx lifecycle, request/response handling, sessions, forms, REST APIs, HTTP clients, routing, CSRF protection, Server-Sent Events, or configuring CommandBox/MiniServer.
8boxlang-configuration
Use this skill when configuring BoxLang runtime settings via boxlang.json, setting environment variables for config overrides, configuring datasources, caches, executors, modules, logging, security, or schedulers — or when helping someone understand the BoxLang configuration system.
8