rss

package module
v0.0.0-...-9f6f10a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2024 License: MIT Imports: 8 Imported by: 0

README

rss

TODO: Use pointer to string types, not types that are pointers to strings.

A Go package for marshaling, unmarshaling, and validating RSS documents.

This package aims to codify the RSS specification in code, making it easier to generate and validate RSS documents.

Overview

This package differs from other implementations of the RSS specification, since it distinguishes between non-existent (nil) and empty values ("").

When marshaling XML using the encoding/xml package, non-existent elements or attributes are omitted using the omitempty field tag:

The XML element for a struct contains marshaled elements for each of the exported fields of the struct, with these exceptions: • a field with a tag including the "omitempty" option is omitted if the field value is empty. The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.

However, when unmarshaling XML a missing element or empty attribute value will be unmarshaled as a zero value. This can cause a valid RSS document in XML form to become invalid when represented as a Go struct.

To handle this issue, pointers are used, such that nil corresponds to a non-existent element or attribute and "" corresponds to an element or attribute with an empty value.

RSS Validation

rss is used by RSS Validator, a web application and command-line utility for validating RSS documents.

Documentation

Overview

Errors for the rss package.

The rss package provides utilities for handling RSS documents. It leverages the RSS 2.0 Specification for determining struct fields used during marshaling, unmarshaling, and validation.

See:

This package relies heavily on the encoding/xml package of the Go standard library:

See:

Some notes on parsing XML:

  • The XMLName field name dictates the name of the XML element representing this struct.
  • If the XML element contains character data, that data is accumulated in the first struct field that has tag ",chardata". The struct field may have type []byte or string. If there is no such field, the character data is discarded.
  • A field with a tag including the "omitempty" option is omitted if the field value is empty. The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.

Utility functions for the rss package.

Index

Constants

View Source
const RSSVERSION = "2.0"

Variables

View Source
var ErrEmptyValue = errors.New("Element must not have empty value")
View Source
var ErrInvalidDate = errors.New("Element must contain a valid date (RFC822)")
View Source
var ErrInvalidElement = errors.New("Element must contain required sub-elements and/or attributes")
View Source
var ErrInvalidMailAddress = errors.New("Element must contain a valid mail address (RFC5322)")
View Source
var ErrInvalidURI = errors.New("Element must contain a valid URI (RFC3986)")
View Source
var ErrInvalidValue = errors.New("Element or attribute must have valid value")
View Source
var ErrNonEmptyValue = errors.New("Element must not have value")

Functions

func IsEmpty

func IsEmpty(s string) (bool, error)

Whether 's' is an empty string.

func IsNotEmpty

func IsNotEmpty(s string) (bool, error)

Whether 's' is not an empty string.

func IsPositiveInteger

func IsPositiveInteger(s string) (bool, error)

Whether 's' is positive integer.

TODO

func IsValidDate

func IsValidDate(s string) (bool, error)

Whether 's' is a valid date (RFC822).

TODO: Valiate day of week.

func IsValidMailAddress

func IsValidMailAddress(s string) (bool, error)

Whether 's' is a valid mail address (RFC5322).

func IsValidURI

func IsValidURI(s string) (bool, error)

Whether 's' is a valid URI (RFC3986).

func Validate

func Validate(r RSSElement) (bool, []error)

In order for an RSS element (RSSElement) to be valid, it must comprise all required elements and sub-elements.

If the RSS element contains optional sub-elements with required elements, these too must be valid.

To accomplish this, we recurse through all struct fields of the struct of interface type RSSElement. If the struct field is of interface type RSSElement, the IsValid method is called. Each RSSElement is responsible for implementing its IsValid method in accordance with the RSS 2.0 Specification.

Types

type Author

type Author struct {
	XMLName  xml.Name `xml:"author"`    // required
	CharData []byte   `xml:",chardata"` // required
}

<author> is an optional sub-element of <item>.

Example:

<author>first.last@example.com</author>

See: https://validator.w3.org/feed/docs/rss2.html#ltauthorgtSubelementOfLtitemgt

func (Author) IsValid

func (r Author) IsValid() (bool, []error)

Returns whether <author> is valid and a slice containing any errors.

type Category

type Category struct {
	XMLName  xml.Name `xml:"category"`              // required
	CharData []byte   `xml:",chardata"`             // required
	Domain   Domain   `xml:"domain,attr,omitempty"` // optional
}

<category> is an optional sub-element of <channel> and <item>.

The <channel>-level category element follows the same rules as the <item>-level category element.

See:

func (Category) IsValid

func (r Category) IsValid() (bool, []error)

Returns whether <category> is valid and a slice containing any errors.

TODO: Check that the value of the element is a forward-slash-separated string.

type Channel

type Channel struct {
	XMLName        xml.Name       `xml:"channel"`                  // required
	Title          Title          `xml:"title"`                    // required
	Link           Link           `xml:"link"`                     // required
	Description    Description    `xml:"description"`              // required
	Language       Language       `xml:"language,omitempty"`       // optional
	Copyright      Copyright      `xml:"copyright,omitempty"`      // optional
	ManagingEditor ManagingEditor `xml:"managingEditor,omitempty"` // optional
	WebMaster      WebMaster      `xml:"webMaster,omitempty"`      // optional
	PubDate        PubDate        `xml:"pubDate,omitempty"`        // optional
	LastBuildDate  LastBuildDate  `xml:"lastBuildDate,omitempty"`  // optional
	Category       Category       `xml:"category,omitempty"`       // optional
	Generator      Generator      `xml:"generator,omitempty"`      // optional
	Docs           Docs           `xml:"docs,omitempty"`           // optional
	Cloud          Cloud          `xml:"cloud,omitempty"`          // optional
	TTL            TTL            `xml:"ttl,omitempty"`            // optional
	Image          Image          `xml:"image,omitempty"`          // optional
	Rating         Rating         `xml:"rating,omitempty"`         // optional
	TextInput      TextInput      `xml:"textInput,omitempty"`      // optional
	SkipHours      SkipHours      `xml:"skipHours,omitempty"`      // optional
	SkipDays       SkipDays       `xml:"skipDays,omitempty"`       // optional
	Item           []*Item        `xml:"item,omitempty"`           // optional
}

<channel> is a required sub-element of <rss>.

See: https://validator.w3.org/feed/docs/rss2.html#requiredChannelElements

func (Channel) IsValid

func (r Channel) IsValid() bool

Whether <channel> is valid.

In order for <channel> to be valid, it must comprise all required elements and sub-elements.

If <channel> contains optional sub-elements with required elements, these too must be valid.

To accomplish this, we recurse through all struct fields. If the struct field is of interface type RSSElement, the IsValid method is called. Each RSSElement is responsible for implementing its IsValid method in accordance with the RSS 2.0 Specification.

type Cloud

type Cloud struct {
	XMLName           xml.Name          `xml:"cloud"`                  // required
	CharData          []byte            `xml:",chardata"`              // prohibited
	Domain            Domain            `xml:"domain,attr"`            // required
	Port              Port              `xml:"port,attr"`              // required
	Path              Path              `xml:"path,attr"`              // required
	RegisterProcedure RegisterProcedure `xml:"registerProcedure,attr"` // required
	Protocol          Protocol          `xml:"protocol,attr"`          // required
}

<cloud> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt

func (Cloud) IsValid

func (r Cloud) IsValid() (bool, []error)

Returns whether <cloud> is valid and a slice containing any errors.

type Comments

type Comments struct {
	XMLName  xml.Name `xml:"comments"`  // required
	CharData []byte   `xml:",chardata"` // required
}

<comments> is an optional sub-element of <item>.

Example:

<comments>https://example.com/comments</comments>`

See: https://validator.w3.org/feed/docs/rss2.html#ltcommentsgtSubelementOfLtitemgt

func (Comments) IsValid

func (r Comments) IsValid() (bool, []error)

Returns whether <comments> is valid and a slice containing any errors.

type Copyright string

<copyright> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Copyright) IsValid

func (r Copyright) IsValid() bool

Whether <copyright> is valid.

type Day

type Day string

<day> is an optional sub-element of <skipDays>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Day) IsValid

func (r Day) IsValid() bool

Whether <day> is valid.

TODO: Check if Monday - Sunday.

type Description

type Description struct {
	XMLName  xml.Name `xml:"description"` // required
	CharData []byte   `xml:",chardata"`   // required
}

<description> is a required sub-element of <channel> and <textInput> and an optional sub-element of <image> and <item>

See:

func (Description) IsValid

func (r Description) IsValid() (bool, []error)

Returns whether <description> is valid and a slice containing any errors.

type Docs

type Docs string

<docs> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Docs) IsValid

func (r Docs) IsValid() bool

Whether <docs> is valid.

type Domain

type Domain *string

'domain' is an optional attribute of <category> and a required attribute of <cloud>.

See:

type Enclosure

type Enclosure struct {
	XMLName  xml.Name `xml:"enclosure"`   // required
	CharData []byte   `xml:",chardata"`   // prohibited
	URL      URL      `xml:"url,attr"`    // required
	Length   Length   `xml:"length,attr"` // required
	Type     Type     `xml:"type,attr"`   // required
}

<enclosure> is an optional sub-element of <item>.

See: https://validator.w3.org/feed/docs/rss2.html#ltenclosuregtSubelementOfLtitemgt

NOTE: In most cases, the <enclosure> element is represented using a self-closing tag:

<enclosure url="..." length="..." type="..." />

From the XML specification,

>The representation of an empty element is either a start-tag immediately
 followed by an end-tag, or an empty-element tag.

Source: https://www.w3.org/TR/xml/#NT-ETag

Self-closing tags are currently not implemented in encoding/xml:

Ideally, both forms (a start-tag immediately followed by an end-tag, or an empty-element tag) represent valid XML, and therefore valid RSS.

func (Enclosure) IsValid

func (r Enclosure) IsValid() (bool, []error)

Returns whether <enclosure> is valid and a slice containing any errors.

type GUID

type GUID struct {
	XMLName     xml.Name     `xml:"guid"`                       // required
	CharData    []byte       `xml:",chardata"`                  // required
	IsPermaLink *IsPermaLink `xml:"isPermaLink,attr,omitempty"` // optional
}

<guid> is an optional sub-element of <item>.

Example:

<guid isPermaLink="true">https://example.com/1337</guid>

See: https://validator.w3.org/feed/docs/rss2.html#ltguidgtSubelementOfLtitemgt

func (GUID) IsValid

func (r GUID) IsValid() (bool, []error)

Returns whether <guid> is valid and a slice containing any errors.

type Generator

type Generator string

<generator> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Generator) IsValid

func (r Generator) IsValid() bool

Whether <generator> is valid.

type Height

type Height string

<height> is an optional sub-element of <image>.

See: https://validator.w3.org/feed/docs/rss2.html#ltimagegtSubelementOfLtchannelgt

func (Height) IsValid

func (r Height) IsValid() bool

Whether <height> is valid.

The maximum value for height is 400, default value is 31.

type Hour

type Hour int

<hour> is an optional sub-element of <skipHours>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Hour) IsValid

func (r Hour) IsValid() bool

Whether <hour> is valid.

type Image

type Image struct {
	XMLName     xml.Name    `xml:"image"`                 // required
	URL         URL         `xml:"url"`                   // required
	Title       Title       `xml:"title"`                 // required
	Link        Link        `xml:"link"`                  // required
	Width       Width       `xml:"width,omitempty"`       // optional
	Height      Height      `xml:"height,omitempty"`      // optional
	Description Description `xml:"description,omitempty"` // optional
}

<image> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#ltimagegtSubelementOfLtchannelgt

TODO: Set default values for width and height.

func (Image) IsValid

func (r Image) IsValid() (bool, []error)

Whether <image> is valid.

type IsPermaLink string

'isPermaLink' is an optional attribute of <guid>.

NOTE: Its default value is true.

See: https://validator.w3.org/feed/docs/rss2.html#ltguidgtSubelementOfLtitemgt

func (IsPermaLink) IsValid

func (r IsPermaLink) IsValid() (bool, []error)

Returns whether 'isPermaLink' is valid and a slice containing any errors.

type Item

type Item struct {
	XMLName     xml.Name     `xml:"item"`                  // required
	Title       *Title       `xml:"title,omitempty"`       // conditionally required
	Link        *Link        `xml:"link,omitempty"`        // optional
	Description *Description `xml:"description,omitempty"` // conditionally required
	Source      *Source      `xml:"source,omitempty"`      // optional
	Enclosure   *Enclosure   `xml:"enclosure,omitempty"`   // optional
	Category    *Category    `xml:"category,omitempty"`    // optional
	PubDate     *PubDate     `xml:"pubDate,omitempty"`     // optional
	GUID        *GUID        `xml:"guid,omitempty"`        // optional
	Comments    *Comments    `xml:"comments,omitempty"`    // optional
	Author      *Author      `xml:"author,omitempty"`      // optional
}

<item> is an optional sub-element of <channel>.

A channel may contain any number of <item>s.

All elements of an item are optional, however at least one of title or description must be present.

See: https://validator.w3.org/feed/docs/rss2.html#hrelementsOfLtitemgt

func (Item) IsValid

func (r Item) IsValid() (bool, []error)

Returns whether <item> is valid and a slice containing any errors.

type Language

type Language string

<language> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Language) IsValid

func (r Language) IsValid() bool

TODO Whether <language> is valid.

The <language> element must be one of the identifiers specified in the current list of ISO 639 language codes:

See:

type LastBuildDate

type LastBuildDate struct {
	XMLName  xml.Name `xml:"lastBuildDate"` // required
	CharData []byte   `xml:",chardata"`     // required
}

<lastBuildDate> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (LastBuildDate) IsValid

func (r LastBuildDate) IsValid() (bool, []error)

Returns whether <lastBuildDate> is valid and a slice containing any errors.

<lastBuildDate> must conform to the Date and Time Specification of RFC822, with the exception that the year may be expressed with two characters or four characters (four preferred).

See: http://asg.web.cmu.edu/rfc/rfc822.html

type Length

type Length *string

'length' is a required attribute of <enclosure>.

See: https://validator.w3.org/feed/docs/rss2.html#ltenclosuregtSubelementOfLtitemgt

type Link struct {
	XMLName  xml.Name `xml:"link"`      // required
	CharData []byte   `xml:",chardata"` // required
}

<link> is a required sub-element of <channel>, <image>, <textInput>, and <item>.

See:

func (Link) IsValid

func (r Link) IsValid() (bool, []error)

Returns whether <link> is valid and a slice containing any errors.

type ManagingEditor

type ManagingEditor string

<managingEditor> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (ManagingEditor) IsValid

func (r ManagingEditor) IsValid() bool

Whether <managingEditor> is valid.

type Name

type Name struct {
	XMLName  xml.Name `xml:"name"`      // required
	CharData []byte   `xml:",chardata"` // required
}

<name> is a required sub-element of <textInput>.

See: https://validator.w3.org/feed/docs/rss2.html#lttextinputgtSubelementOfLtchannelgt

func (Name) IsValid

func (r Name) IsValid() (bool, []error)

Returns whether <name> is valid and a slice containing any errors.

type Path

type Path *string

'path' is required attribute of <cloud>.

See: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt

type Port

type Port *string

'port' is required attribute of <cloud>.

See: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt

type Protocol

type Protocol *string

'protocol' is required attribute of <cloud>.

See: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt

type PubDate

type PubDate struct {
	XMLName  xml.Name `xml:"pubDate"`   // required
	CharData []byte   `xml:",chardata"` // required
}

<pubDate> is an optional sub-element of <channel> and <item>.

See:

func (PubDate) IsValid

func (r PubDate) IsValid() (bool, []error)

Returns whether <pubDate> is valid and a slice containing any errors.

<pubDate> must conform to the Date and Time Specification of RFC822, with the exception that the year may be expressed with two characters or four characters (four preferred).

See: http://asg.web.cmu.edu/rfc/rfc822.html

type RSS

type RSS struct {
	XMLName xml.Name `xml:"rss"`          // required
	Version Version  `xml:"version,attr"` // required
	Channel *Channel `xml:"channel"`      // required
}

At the top level, a RSS document is a <rss> element, with a mandatory attribute called version, that specifies the version of RSS that the document conforms to. If it conforms to this specification, the version attribute must be 2.0.

Subordinate to the <rss> element is a single <channel> element, which contains information about the channel (metadata) and its contents.

See:

func (RSS) IsValid

func (r RSS) IsValid() (bool, []error)

Whether <rss> is valid.

type RSSElement

type RSSElement interface {
	IsValid() (bool, []error)
}

The RSSElement interface specifies a single method, IsValid. IsValid checks whether the element conforms to the RSS 2.0 Specification.

type Rating

type Rating string

<rating> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (Rating) IsValid

func (r Rating) IsValid() bool

Whether <rating> is valid.

type RegisterProcedure

type RegisterProcedure *string

'registerProcedure' is required attribute of <cloud>.

See: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt

type SkipDays

type SkipDays struct {
	XMLName xml.Name `xml:"skipDays"` // required
	Day     []*Day   `xml:"hour"`     // required
}

<skipDays> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (SkipDays) IsValid

func (r SkipDays) IsValid() bool

Whether <skipDays> is valid.

This element contains up to seven <day> sub-elements whose value is Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday.

type SkipHours

type SkipHours struct {
	XMLName xml.Name `xml:"skipHours"` // required
	Hour    []*Hour  `xml:"hour"`      // required
}

<skipHours> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (SkipHours) IsValid

func (r SkipHours) IsValid() bool

Whether <skipHours> is valid.

This element contains up to 24 <hour> sub-elements whose value is a number between 0 and 23.

type Source

type Source struct {
	XMLName  xml.Name `xml:"source"`    // required
	CharData []byte   `xml:",chardata"` // optional
	URL      URL      `xml:"url,attr"`  // required
}

<source> is an optional sub-element of <item>.

See: https://validator.w3.org/feed/docs/rss2.html#ltsourcegtSubelementOfLtitemgt

func (Source) IsValid

func (r Source) IsValid() (bool, []error)

Returns whether <source> is valid and a slice containing any errors.

type TTL

type TTL struct {
	XMLName  xml.Name `xml:"ttl"`       // required
	CharData []byte   `xml:",chardata"` // required
}

<ttl> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#ltttlgtSubelementOfLtchannelgt

func (TTL) IsValid

func (r TTL) IsValid() (bool, []error)

Returns whether <ttl> is valid and a slice containing any errors.

type TextInput

type TextInput struct {
	XMLName     xml.Name     `xml:"textInput"`   // required
	Title       *Title       `xml:"title"`       // required
	Description *Description `xml:"description"` // required
	Name        *Name        `xml:"name"`        // required
	Link        *Link        `xml:"link"`        // required
}

<textInput> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#lttextinputgtSubelementOfLtchannelgt

func (TextInput) IsValid

func (r TextInput) IsValid() (bool, []error)

Returns whether <textInput> is valid and a slice containing any errors.

type Title

type Title struct {
	XMLName  xml.Name `xml:"title"`     // required
	CharData []byte   `xml:",chardata"` // required
}

<title> is a required sub-element of <channel>, <textInput>, and <item>.

See:

func (Title) IsValid

func (r Title) IsValid() (bool, []error)

Returns whether <title> is valid and a slice containing any errors.

type Type

type Type *string

'type' is a required attribute of <enclosure>.

See: https://validator.w3.org/feed/docs/rss2.html#ltenclosuregtSubelementOfLtitemgt

type Version

type Version string

version is a required attribute of <rss>.

See: https://validator.w3.org/feed/docs/rss2.html#whatIsRss

func (Version) IsValid

func (r Version) IsValid() bool

Whether version is valid.

<rss> must contain "version" attribute with value "2.0".

NOTE: A version 0.91 or 0.92 file is also a valid 2.0 file.

type WebMaster

type WebMaster string

<webMaster> is an optional sub-element of <channel>.

See: https://validator.w3.org/feed/docs/rss2.html#optionalChannelElements

func (WebMaster) IsValid

func (r WebMaster) IsValid() bool

Whether <webMaster> is valid.

type Width

type Width string

<width> is an optional sub-element of <image>.

See: https://validator.w3.org/feed/docs/rss2.html#ltimagegtSubelementOfLtchannelgt

func (Width) IsValid

func (r Width) IsValid() bool

Whether <width> is valid.

The maximum value for width is 144, default value is 88.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL