commit - 3f7e247f5e371934a15857d90f183e254bec9d2d
commit + 33d9e23c99af8e8c059dd587cf9ee8d61734d300
blob - /dev/null
blob + d986c6ded9e2e83b290615711c1b70716666633d (mode 644)
--- /dev/null
+++ atom/atom.go
+// Package atom implements decoding encoding of Atom feeds as
+// specified in RFC 4287.
+package atom
+
+import (
+ "encoding/xml"
+ "time"
+)
+
+const xmlns = "http://www.w3.org/2005/Atom"
+
+// MediaType is Atom's IANA media type.
+const MediaType = "application/atom+xml"
+
+type Feed struct {
+ ID string `xml:"id"`
+ Title string `xml:"title"`
+ Updated time.Time `xml:"updated"`
+ Author *Author `xml:"author,omitempty"`
+ Link []Link `xml:"link,omitempty"`
+ Subtitle string `xml:"subtitle,omitempty"`
+ Entries []Entry `xml:"entry"`
+}
+
+type feed struct {
+ XMLName struct{} `xml:"feed"`
+ Namespace string `xml:"xmlns,attr"`
+ *Feed
+}
+
+type Author struct {
+ Name string `xml:"name"`
+ URI string `xml:"uri,omitempty"`
+ Email string `xml:"email,omitempty"`
+}
+
+type Entry struct {
+ ID string `xml:"id"`
+ Title string `xml:"title"`
+ Updated time.Time `xml:"updated,omitempty"`
+ Author *Author `xml:"author,omitempty"`
+ Links []Link `xml:"link"`
+ Summary string `xml:"summary,omitempty"`
+ Content []byte `xml:"content,omitempty"`
+ Published *time.Time `xml:"published,omitempty"`
+}
+
+type Link struct {
+ HRef string `xml:"href,attr,omitempty"`
+ Rel string `xml:"rel,attr,omitempty"`
+ Type string `xml:"type,attr,omitempty"`
+}
+
+func Marshal(f *Feed) ([]byte, error) {
+ f1 := &feed{
+ Namespace: xmlns,
+ Feed: f,
+ }
+ return xml.MarshalIndent(f1, "", "\t")
+ // b = bytes.ReplaceAll(b, []byte("></link>"), []byte("/>"))
+ // return b, err
+}
blob - /dev/null
blob + 5e54cfd439080b97125d2e85958079a61f1726f9 (mode 644)
--- /dev/null
+++ atom/atom_test.go
+package atom
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "os"
+ "testing"
+ "time"
+)
+
+func TestMarshal(t *testing.T) {
+ f := &Feed{
+ Title: "Example Feed",
+ Link: []Link{
+ {HRef: "http://example.org/"},
+ },
+ Updated: time.Date(2003, time.Month(12), 13, 18, 30, 2, 0, time.UTC),
+ Author: &Author{Name: "John Doe"},
+ ID: "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
+ Entries: []Entry{
+ {
+ Title: "Atom-Powered Robots Run Amok",
+ ID: "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+ Links: []Link{
+ {HRef: "http://example.org/2003/12/13/atom03"},
+ },
+ Updated: time.Date(2003, time.Month(12), 13, 18, 30, 2, 0, time.UTC),
+ Summary: "Some text.",
+ },
+ },
+ }
+ feed1 := &feed{
+ Namespace: xmlns,
+ Feed: f,
+ }
+ got, err := xml.MarshalIndent(feed1, "", " ")
+ if err != nil {
+ t.Fatal(err)
+ }
+ got = bytes.ReplaceAll(got, []byte("></link>"), []byte("/>"))
+
+ want, err := os.ReadFile("testdata/1.xml")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(got, want) {
+ t.Errorf("oops")
+ fmt.Fprintln(os.Stderr, string(got))
+ }
+}
blob - /dev/null
blob + 2fd7e73c373369d952ba24c0458bd53a26e6f2e7 (mode 644)
--- /dev/null
+++ atom/testdata/1.xml
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title>Example Feed</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <link href="http://example.org/"/>
+ <entry>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <title>Atom-Powered Robots Run Amok</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <summary>Some text.</summary>
+ </entry>
+</feed>
\ No newline at end of file
blob - /dev/null
blob + 328e2caaa79eadf4fc62b1d93671afd90599d59a (mode 644)
--- /dev/null
+++ atom/testdata/2.xml
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">dive into mark</title>
+ <subtitle type="html">
+ A <em>lot</em> of effort
+ went into making this effortless
+ </subtitle>
+ <updated>2005-07-31T12:29:29Z</updated>
+ <id>tag:example.org,2003:3</id>
+ <link rel="alternate" type="text/html"
+ hreflang="en" href="http://example.org/"/>
+ <link rel="self" type="application/atom+xml"
+ href="http://example.org/feed.atom"/>
+ <rights>Copyright (c) 2003, Mark Pilgrim</rights>
+ <generator uri="http://www.example.com/" version="1.0">
+ Example Toolkit
+ </generator>
+ <entry>
+ <title>Atom draft-07 snapshot</title>
+ <link rel="alternate" type="text/html"
+ href="http://example.org/2005/04/02/atom"/>
+ <link rel="enclosure" type="audio/mpeg" length="1337"
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
+ <id>tag:example.org,2003:3.2397</id>
+ <updated>2005-07-31T12:29:29Z</updated>
+ <published>2003-12-13T08:29:29-04:00</published>
+ <author>
+ <name>Mark Pilgrim</name>
+ <uri>http://example.org/</uri>
+ <email>f8dy@example.com</email>
+ </author>
+ <contributor>
+ <name>Sam Ruby</name>
+ </contributor>
+ <contributor>
+ <name>Joe Gregorio</name>
+ </contributor>
+ <content type="xhtml" xml:lang="en"
+ xml:base="http://diveintomark.org/">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p><i>[Update: The Atom draft is finished.]</i></p>
+ </div>
+ </content>
+ </entry>
+</feed>