BoxLang 🚀 A New JVM Dynamic Language Learn More...
📡 A comprehensive RSS/Atom feed module for BoxLang that brings full-featured feed reading and creation capabilities to your applications!
This module provides powerful RSS and Atom feed capabilities to the BoxLang language, making it easy to read, parse, create, and manage syndication feeds with minimal code.
maxItems parametercffeed tagIf you are using CommandBox for your web applications, simply run:
box install bx-rss
The module will automatically register and be available as
bxrss in your BoxLang applications.
The simplest way to read an RSS feed is with the rss() function:
feedData = rss( "https://example.com/feed.xml" );
println( "Found #feedData.items.size()# items" );
println( "Feed title: #feedData.channel.title#" );
You can also use the <bx:feed> component for more control:
bx:feed
action="read"
source="https://example.com/feed.xml"
result="feedData";
println( "Found #feedData.items.size()# items" );
println( "Feed title: #feedData.channel.title#" );
That's it! 🎉 You now have feed data parsed and ready to use.
💡 Pro Tip: The rss() BIF is perfect
for quick feed reading, while the component gives you more options
like multiple output variables, file writing, and creating feeds.
The module supports two core operations:
Parse existing RSS/Atom feeds from URLs or files.
items array and
channel metadataGenerate new RSS/Atom feeds from your data.
<bx:feed> ComponentThe main component for all RSS/Atom feed operations.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
action
| string | No | "read"
| Action to perform: "read" or "create"
|
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
source
| string | Yes | - | URL or file path to the feed |
result
| string | No | - | Variable name to store full feed structure (items + channel) |
name
| string | No | - | Alias for
result (backward compatibility) |
properties
| string | No | - | Variable name to store channel metadata only |
query
| string | No | - | Variable name to store items array only |
xmlVar
| string | No | - | Variable name to store raw XML string |
outputFile
| string | No | - | File path to write the feed XML |
overwrite
| boolean | No | false
| Whether to overwrite existing output file |
timeout
| numeric | No | 60
| HTTP timeout in seconds |
userAgent
| string | No | "BoxLang-RSS-Module/1.0"
| Custom User-Agent for HTTP requests |
maxItems
| numeric | No | 0
| Maximum items to return (0 = no limit) |
itunes
| boolean | No | false
| Force iTunes podcast reader |
mediaRss
| boolean | No | false
| Force Media RSS reader |
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
properties
| struct | Yes | - | Feed metadata (title, description, link, etc.) |
data
| array/query | Yes | - | Feed items/entries |
name
| struct | No | - | Alternative: full feed structure (properties + items) |
query
| any | No | - | Alias for
data (backward compatibility) |
columnMap
| struct | No | - | Map query columns to feed fields |
xmlVar
| string | No | - | Variable name to store generated XML |
outputFile
| string | No | - | File path to write the feed XML |
overwrite
| boolean | No | false
| Whether to overwrite existing output file |
escapeChars
| boolean | No | false
| Escape special characters in content |
Read and display feed items:
bx:feed
action="read"
source="https://example.com/blog/feed.xml"
result="feedData";
println( "Blog: #feedData.channel.title#" );
println( "Items: #feedData.items.size()#" );
feedData.items.each( function( item ) {
println( "- #item.title#: #item.link#" );
} );
💡 Use Case: Display latest blog posts or news articles.
Automatically detects and includes iTunes podcast fields:
bx:feed
action="read"
source="https://feeds.example.com/podcast.xml"
result="podcast";
println( "Podcast: #podcast.channel.title#" );
println( "Author: #podcast.channel.itunesAuthor#" );
podcast.items.each( function( episode ) {
println( "Episode: #episode.itunesTitle#" );
println( "Duration: #episode.itunesDuration#" );
println( "Season #episode.itunesSeason# Episode #episode.itunesEpisode#" );
} );
💡 Use Case: Display podcast episodes with rich metadata.
Automatically detects and includes Media RSS thumbnail/content fields:
bx:feed
action="read"
source="https://vimeo.com/channels/staffpicks/videos/rss"
result="videos";
videos.items.each( function( video ) {
println( "Video: #video.title#" );
if( !isNull( video.mediaThumbnail ) ) {
println( "Thumbnail: #video.mediaThumbnail.url#" );
println( "Size: #video.mediaThumbnail.width#x#video.mediaThumbnail.height#" );
}
} );
💡 Use Case: Display video feeds with thumbnails.
Apply custom filters to feed items:
bx:feed
action="read"
source="https://news.example.com/feed.xml"
result="recentNews"
maxItems="10";
println( "Latest 10 news items:" );
recentNews.items.each( function( item ) {
println( "- #item.title# (#dateFormat( item.publishedDate )#)" );
} );
💡 Use Case: Display latest N items from a feed.
Use different output variables simultaneously:
bx:feed
action="read"
source="https://example.com/feed.xml"
result="fullFeed"
properties="metadata"
query="items"
xmlVar="rawXml"
outputFile="/tmp/cached-feed.xml"
overwrite="true";
// fullFeed has both items and channel
println( "Full structure: #fullFeed.items.size()# items" );
// metadata has only channel info
println( "Feed title: #metadata.title#" );
// items has only the items array
println( "Just items: #items.size()# entries" );
// rawXml has the original XML
println( "XML length: #rawXml.len()# characters" );
💡 Use Case: Flexible data access for different use cases.
Generate an RSS 2.0 feed from your data:
feedProps = {
"version": "rss_2.0",
"title": "My Blog",
"link": "https://myblog.com",
"description": "Latest posts from my blog",
"publishedDate": now()
};
feedItems = [
{
"title": "First Post",
"link": "https://myblog.com/post-1",
"description": "This is my first blog post",
"publishedDate": now(),
"author": "[email protected]"
},
{
"title": "Second Post",
"link": "https://myblog.com/post-2",
"description": "Another great post",
"publishedDate": dateAdd( "d", -1, now() ),
"author": "[email protected]"
}
];
bx:feed
action="create"
properties=feedProps
data=feedItems
xmlVar="feedXml"
outputFile="/var/www/feeds/blog.xml"
overwrite="true";
println( "Feed created with #feedItems.size()# items" );
💡 Use Case: Expose your content as an RSS feed.
Generate a podcast feed with iTunes extensions:
podcastProps = {
"version": "rss_2.0",
"title": "My Podcast",
"link": "https://mypodcast.com",
"description": "Weekly tech discussions",
"publishedDate": now(),
"itunesAuthor": "John Doe",
"itunesSubtitle": "Tech Talk",
"itunesSummary": "In-depth discussions about technology",
"itunesImage": "https://mypodcast.com/artwork.jpg",
"itunesExplicit": "false",
"itunesCategories": ["Technology", "Business"]
};
episodes = [
{
"title": "Episode 1: Getting Started",
"link": "https://mypodcast.com/episode-1",
"description": "Our first episode",
"publishedDate": now(),
"author": "[email protected]",
"itunesTitle": "Getting Started with Tech",
"itunesDuration": "00:45: 30",
"itunesEpisode": "1",
"itunesSeason": "1",
"itunesEpisodeType": "full",
"enclosure": {
"url": "https://mypodcast.com/episodes/episode-1.mp3",
"type": "audio/mpeg",
"length": "45000000"
}
}
];
bx:feed
action="create"
properties=podcastProps
data=episodes
outputFile="/var/www/feeds/podcast.xml"
overwrite="true";
💡 Use Case: Create a podcast feed for Apple Podcasts, Spotify, etc.
Merge items from multiple feeds:
sources = [
"https://blog1.example.com/feed.xml",
"https://blog2.example.com/feed.xml",
"https://blog3.example.com/feed.xml"
];
bx:feed
action="read"
source=sources
result="aggregated"
maxItems="20";
println( "Aggregated #aggregated.items.size()# items from #sources.size()# feeds" );
// Items are automatically sorted by date
aggregated.items.each( function( item ) {
println( "[#item.feed#] #item.title#" );
} );
💡 Use Case: Create a feed aggregator or news reader.
Generate feed from database query results:
// Get blog posts from database
posts = queryExecute(
"SELECT title, url, content, published_date, author_email
FROM blog_posts
WHERE status = 'published'
ORDER BY published_date DESC
LIMIT 50",
[]
);
feedProps = {
"version": "rss_2.0",
"title": "Company Blog",
"link": "https://company.com/blog",
"description": "Latest news and updates"
};
// Map query columns to feed fields
columnMap = {
"title": "title",
"link": "url",
"description": "content",
"publishedDate": "published_date",
"author": "author_email"
};
bx:feed
action="create"
properties=feedProps
data=posts
columnMap=columnMap
outputFile="/var/www/public/feed.xml"
overwrite="true";
💡 Use Case: Generate feeds from database content.
Use custom User-Agent for HTTP requests:
bx:feed
action="read"
source="https://api.example.com/feed.xml"
result="feedData"
userAgent="MyApp/2.0 (+https://myapp.com/bot)"
timeout="30";
💡 Use Case: Identify your application to feed providers.
The RSS module automatically detects and includes extension fields (iTunes podcast, Media RSS) when they are present in a feed, without requiring you to explicitly enable them.
Auto-Detection Process:
itunes or mediaRss flags are
specified, the module starts with the iTunes readerExplicit Override:
// Force iTunes reader (even if feed has no iTunes fields)
bx:feed source="feed.xml" result="data" itunes="true";
// Force Media RSS reader (even if feed has iTunes fields)
bx:feed source="feed.xml" result="data" mediaRss="true";
When iTunes podcast extensions are detected, these additional fields are available:
Channel Level (in feedData.channel):
itunesAuthor - Podcast authoritunesSubtitle - Podcast subtitleitunesSummary - Longer descriptionitunesImage - Artwork URLitunesExplicit - Content rating (true/false)itunesCategories - Array of category stringsitunesOwnerName - Owner nameitunesOwnerEmail - Owner email
Item Level (in each feedData.items[]):
itunesTitle - Episode titleitunesDuration - Duration (HH:MM: SS format)itunesEpisode - Episode numberitunesSeason - Season numberitunesEpisodeType - Type (full, trailer, bonus)itunesExplicit - Episode content ratingitunesAuthor - Episode authoritunesSummary - Episode summaryitunesSubtitle - Episode subtitleitunesImage - Episode artwork URLWhen Media RSS extensions are detected, these additional fields are available:
Item Level (in each feedData.items[]):
mediaThumbnail - Struct with: url - Thumbnail image URLwidth - Image width in pixelsheight - Image height in pixelstime - Time offset (for video thumbnails)rss() FunctionThe module also provides a rss() Built-In Function (BIF)
for quick feed reading:
// Simple usage
feedData = rss( "https://example.com/feed.xml" );
// With options
feedData = rss(
urls = "https://example.com/feed.xml",
maxItems = 10,
timeout = 30
);
// Multiple feeds
feedData = rss(
urls = [
"https://blog1.com/feed.xml",
"https://blog2.com/feed.xml"
]
);
Parameters:
urls (string/array, required) - Feed URL(s) to readfilter (function, optional) - Filter function for itemsmaxItems (numeric, optional) - Maximum items to return
(default: 0 = all)itunes (boolean, optional) - Force iTunes reader
(default: false = auto-detect)mediaRss (boolean, optional) - Force Media RSS reader
(default: false = auto-detect)userAgent (string, optional) - Custom User-Agenttimeout (numeric, optional) - Timeout in seconds
(default: 25)
Returns: Struct with items array and
channel metadata
Problem: Feed fails to parse or returns no items.
Solutions:
Problem: iTunes or Media RSS fields are missing.
Solutions:
itunes="true" or mediaRss="true"
xmlVar attributeProblem: Generated feed is invalid or won't display.
Solutions:
escapeChars="true" if content has HTMLProblem: Feed won't save to file.
Solutions:
overwrite="true" to replace
existing files"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" Jn 14:1-12
Copyright Since 2023 by Ortus Solutions, Corp
www.boxlang.io | www.ortussolutions.com
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
$
box install bx-rss