home
NOTE: Under Construction - I'm in the middle of upgrading my site and lots of stuff is kinda broken. Please forgive the mess.

Create An Atom Feed In Rust

January 2024

Introduction

This is what I'm doing to make an Atom feed for my site. More notes below the code.

Code
//! ```cargo
//! [dependencies]
//! atom_syndication = "0.12.2"
//! chrono = { version = "0.4.26", features = ["std"] }
//! uuid = { version = "1.6.1", features = ["v5"] }
//! ```

use atom_syndication::*;
use chrono::prelude::*;
use std::collections::BTreeMap;
use std::fs;
use uuid::Uuid;


fn main() {

  let feed_constant_uuid4 = Uuid::try_parse(
    "b71fc261-fc1a-4220-b43f-2be4b216c0b2"
  ).unwrap();

  let generation_date = chrono::offset::Utc::now().fixed_offset();

  let author = Person {
    name: "Alan W. Smith".to_string(), 
    email: None,
    uri: Some("https://www.example.com/".to_string())
  };

  let entry_uuid5 = format!("urn:uuid:{}", Uuid::new_v5(
    &feed_constant_uuid4, b"unque_file_id_alfa")
      .as_hyphenated()
      .to_string()
  );

  let entry_title = Text {
    value: "This Is A Title".to_string(),
    base: None, 
    lang: None,
    r#type: TextType::Text
  };

  let tz_hour_offset = 5; 
  let tz = FixedOffset::west_opt(tz_hour_offset * 60 * 60).unwrap();
  let updated_date = NaiveDateTime::parse_from_str("2023-12-17 10:33:55", "%Y-%m-%d %H:%M:%S")
    .unwrap()
    .and_local_timezone(tz)
    .unwrap();

  let entry_content = Some(
    Content {
      base: None, 
      lang: None, 
      value: Some("<p>Hello, world</p>".to_string()),
      src: Some("https://www.example.com/some_path.html".to_string()),
      content_type: Some("html".to_string()),
    }
  );

  let entry = Entry {
      id: entry_uuid5,
      title: entry_title,
      authors: vec![author.clone()],
      categories: vec![],
      content: entry_content,
      summary: None, 
      source: None,
      rights: None, 
      published: None, 
      links: vec![],
      contributors: vec![],
      updated: updated_date,
      extensions: BTreeMap::new() 
  };

  let entries = vec![entry];

  let feed_id = format!(
    "urn:uuid:{}",
    feed_constant_uuid4.as_hyphenated()
  );

  let feed_link = Link{
    href: "https://www.example.com/atom.xml".to_string(),
    rel: "self".to_string(),
    hreflang: None, 
    length: None, 
    mime_type: None,
    title: None
  };

  let feed = Feed {
    title: "My Example Feed".into(),
    id: feed_id,
    updated: generation_date,
    authors: vec![author],
    links: vec![feed_link],
    entries,
    ..Default::default()
  };

  let config = WriteConfig {
    write_document_declaration: true,
    indent_size: Some(2),
  };

  let file = fs::OpenOptions::new()
    .create(true)
    .truncate(true)
    .write(true)
    .open("/Users/alan/Desktop/atom-test.xml").unwrap();

  // output the file
  feed.write_with_config(&file, config).unwrap();

  // print it for demo
  println!("{}", feed.to_string());
}
Code
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>My Example Feed</title>
  <id>urn:uuid:b71fc261-fc1a-4220-b43f-2be4b216c0b2</id>
  <updated>2024-01-02T23:29:27.999342+00:00</updated>
  <author>
    <name>Alan W. Smith</name>
    <uri>https://www.example.com/</uri>
  </author>
  <link href="https://www.example.com/atom.xml" rel="self"/>
  <entry>
    <title>This Is A Title</title>
    <id>urn:uuid:b1507332-d46c-5bcf-929a-f89c59e01bac</id>
    <updated>2023-12-17T10:33:55+05:00</updated>
    <author>
      <name>Alan W. Smith</name>
      <uri>https://www.example.com/</uri>
    </author>
    <content type="html" src="https://www.example.com/some_path.html">&lt;p&gt;Hello, world&lt;/p&gt;</content>
  </entry>
</feed>
═══ § ═══

Footnotes And References