Skip to content
Switch branches/tags


Build Status Maven Central Maven Central (snapshot) Codacy Badge Codecov Gitter



  • Efficient and strict parsing of OPDS 1.2 feeds
  • Extensible parser for consuming extension data inserted into feeds in a type-safe manner
  • Explicit support for registering parser extensions via ServiceLoader
  • Parsed feeds exposed as immutable and persistent data types for correctness and thread-safety
  • ISC license
  • High coverage automated test suite
  • OSGi-ready


Install the Android SDK. The package has no dependencies on the Android API and is therefore usable in non-Android projects.

$ ./gradlew clean assemble check

If the above fails, it's a bug. Report it!


Use the following Maven or Gradle dependencies, replacing ${LATEST_VERSION_HERE} with whatever is the latest version published to Maven Central:

<!-- API -->

<!-- Parser API -->

<!-- Default implementation -->
repositories {

implementation "one.irradia.opds1_2:one.irradia.opds1_2.api:${LATEST_VERSION_HERE}"
implementation "one.irradia.opds1_2:one.irradia.opds1_2.parser.api:${LATEST_VERSION_HERE}"
implementation "one.irradia.opds1_2:one.irradia.opds1_2.parser.vanilla:${LATEST_VERSION_HERE}"

Library code is encouraged to depend only upon the API package in order to give consumers the freedom to use other implementations of the API if desired.


Most real-life OPDS feeds contain metadata expressed as values taken from XML schemas outside of the core OPDS schema. The one.irradia.opds1_2 package exposes this extra data by requiring consumers to opt-in to extension data collection by specifying a list of extension parsers when parsing OPDS feeds. Extension data that cannot be consumed by any extension parser is silently ignored. As an example, if a user wants to parse a feed and wants to receive any Dublin Core metadata that may be included:

val parsers : OPDS12FeedParserProviderType

val parser =
    uri = URI.create("urn:example"),
    stream = open("feed.xml"),
    extensionEntryParsers = listOf(OPDSDublinFeedParsers()),
    extensionParsers = listOf(OPDS12DublinFeedEntryParsers()))

val result = parser.parse()

Assuming that parsing succeeds, the Dublin Core metadata can be accessed by filtering the list of extension values for values of type one.irradia.opds1_2.dublin.OPDS12DublinCoreValue:

val extensions =

Consult the documentation for each extension parser to see what types of values can be returned.


Module Description
one.irradia.opds1_2.api Core API
one.irradia.opds1_2.commons Common code shared between implementations
one.irradia.opds1_2.dublin Dublin Core extensions
one.irradia.opds1_2.lexical Lexical types used by parsers
one.irradia.opds1_2.nypl Functionality specific to NYPL OPDS feeds
one.irradia.opds1_2.parser.api Parser API
one.irradia.opds1_2.parser.extension.spi Parser extension SPI
one.irradia.opds1_2.tests.device Unit tests that execute on real or emulated devices
one.irradia.opds1_2.tests Unit tests that can execute without needing a real or emulated device
one.irradia.opds1_2.vanilla Vanilla parser implementation

Publishing Releases

Releases are published to Maven Central with the following invocation:

$ ./gradlew clean assemble publish closeAndReleaseRepository

Consult the documentation for the Gradle Signing plugin and the Gradle Nexus staging plugin for details on what needs to go into your ~/.gradle/ file to do the appropriate PGP signing of artifacts and uploads to Maven Central.

Semantic Versioning

All packages obey Semantic Versioning once they reach version 1.0.0.