Installation
Install mediaxml
with npm
:
$ npm install mediaxml
Or add to package.json
:
{
"dependencies": {
"mediaxml": "^0.4.0"
}
}
See the Getting Started guide for more information
on using the mediaxml
module.
Getting Started
The mediaxml module provides various implementations of XML formats for describing media packages, manifests, and feeds such as RSS, mRSS, ADI, and XMLTV.
Simple Example
In the example below, we parse a rss feed and enumerate all of the items in the document's channel.
const path = require('path')
const rss = require('mediaxml/rss')
const fs = require('fs')
const stream = fs.createReadStream('feed.rss')
const document = rss.createDocument(stream)
document.ready(() => {
for (const item of document.channel.items) {
console.log(item.title, item.description, item.link)
}
})
Parsing Documents
Parsing a XML document using streams:
const { Parser } = require('mediaxml/parser')
const path = require('path')
const fs = require('fs')
const stream = fs.createReadStream('epg.xml')
const parser = new Parser()
stream.pipe(parser.createWriteStream()).on('finish', () => {
console.log(parser.rootNode.sourceInfoUrl, parser.rootNode.sourceInfoName)
console.log(parser.rootNode.children)
parser.createReadStream().pipe(process.stdout)
})
Querying the Document Object Model
The query API is a powerful tool for querying the document object model produced by the parser using JSONata query syntax with a preprocessor syntax.
const { rootNode } = parser
// query root node decendent nodes with tag name "channel"
const channels = rootNode.query('[name="channel"]')
// query root node decendent nodes with a tag name "programme"
const programmes = rootNode.query('[name="programme"]')
// query all nodes in document with tag name "category"
// and select the text content (selected with the `:text` preprocessor function)
const categories = rootNode.query('**[name="category"]:text')
// query all nodes in document with tag name "programme"
// an `start` attribute (selected with the `attr()` preprocessor function)
// integer value greater than todays
const programmesInFuture = rootNode.query(`[
name = "programmes" AND
$int(attr(start)) > $int("${Date()}")
]`)
Creating Documents
const { createDocument } = require('mediaxml/document')
const document = createDocument({ nodeName: 'ADI' })
const metadata = document.createChild('Metadata')
metadata.createChild('AMS', {
Asset_Class: 'package',
Provider_ID: 'mylifetime.com',
Provider: 'LIFETIMEMOVIECLUB_HD_UNIFIED',
Product: 'SVOD',
...
})
metadata.createChild('App_Data', {
App: 'SVOD',
Name: 'Metadata_Spec_Version',
Value: 'CableLabsVOD1'
})
metadata.createChild('App_Data', {
App: 'SVOD',
Name: 'Provider_Content_Tier',
Value: 'LIFETIMEMOVIECLUB_HD_UNIFIED'
})
console.log(document.toString())
// <ADI>
// <Metadata>
// <AMS Asset_Class="package" Product="SVOD" Provider="LIFETIMEMOVIECLUB_HD_UNIFIED" Provider_ID="mylifetime.com" Verb="" Version_Major="3" Version_Minor="0" Creation_Date="2020-09-29" Description="AcquiredMovie_FriendsWhoKill_241958-package" Asset_ID="LFHP2419582007240000" Asset_Name="LFHP2419582007240000_AMVE_HD" />
// <App_Data App="SVOD" Name="Metadata_Spec_Version" Value="CableLabsVOD1.1" />
// <App_Data App="SVOD" Name="Provider_Content_Tier" Value="LIFETIMEMOVIECLUB_HD_UNIFIED" />
// </Metadata>
// </ADI>
See Also
Usage
General Usage
The mediaxml
module exports various APIs that allow for the parsing
and building of XML documents intended for media packaging and
metadata purposes. This includes support for metadata package specifications
like CableLabsVOD1.1 (ADI) and SCTE-236 (ADI3) as well support for feeds like
RSS, mRSS, and XMLTV. The mediaxml
module provides low level components for
parsing and building documents in a variety of ways that make this a
convenient tool. The document object defined by mediaxml
can be
queried with a JSONata syntax extended with
special selectors
Parsing Documents
XML documents can be parsed easily with the Parser
class from the
mediaxml/parser
module.
const { Parser } = require('mediaxml/parser')
The Parser
class can provide a Writable
stream interface a
Readable
stream can pipe to.
const parser = new Parser()
process.stdin.pipe(parser.createWriteStream()).on('finish', () => {
console.log(parser.rootNode)
})
The Parser
instance can be directly written to.
const parser = new Parser()
parser.write(source)
parser.end()
The static Parser.from(input)
function can be convenient for creating
a Parser
instance from an input string (or stream).
const parser = Parser.from(source)
The Parser
instance state can be serialized with the
parser.toString()
function.
const sourceString = parser.toString()
Querying Document Object Model
Document nodes can be queried using "JSONata" query
syntax with special selector syntax for working with Node
(ParserNode
)
instances represented by a document object model.
See the query(node, query, opts)
for more
information on how the API works and how to query the node hierarchy.
Below are a few examples.
// select first node in document with node name "channel"
const channel = document.query('[name="channel"]:first')
// select the 'href' attribute value from the first child with a node name
// of "atom:link" from the first "channel" node
const atom = document.query('[name="channel"]:first:children:first[name="atom:link"]:attr(href)')
// select the text of the first node with a name that matches the
`/^offer:BillingId$/i` regular expression
const billingId = document.query('**[name ~> /^offer:BillingId$/i]:first:text')
Document & Node Building
Documents can be created easily with the createDocument(source)
and
createNode(name, attributes, body)
factory functions in the
mediaxml/document
module.
const { createDocument, createNode } = require('mediaxml/document')
Documents can be created inline from a source string or from a stream as input.
const document = createDocument(`
<package>
<assets />
</package>
`)
console.log('%s', document)
// <package>
// <assets />
// </package>
Nodes can be created easily with createNode(name, attributes, body)
and appended to the document with document.appendChild(child)
document.appendChild(createNode('asset', {
name: 'first',
url: 'https://example.com/first.mp4'
}))
document.appendChild(createNode('asset', {
name: 'second',
url: 'https://example.com/second.mp4'
}))
console.log('%s', document)
// <package>
// <assets>
// <asset name="first" url="https://example.com/first.mp4" />
// <asset name="second" url="https://example.com/second.mp4" />
// </assets>
// </package>
Querying the nodes of the document should work as expected with the
document.query(query)
function.
const assets = document.query('**[name="asset"]')
console.log(assets) // a `ParserNodeFragment` is just a fancy `Array`
// ParserNodeFragment(2) [
// <asset name="first" url="https://example.com/first.mp4" />,
// <asset name="second" url="https://example.com/second.mp4" />
// ]
const urls = document.query('**[name="asset"]:attr(url)')
console.log(urls)
// [ 'https://example.com/first.mp4', 'https://example.com/second.mp4 ]
Custom Documents
Custom documents can be created easily by extending the Document
and
Node
classes.
const { Document, Node } = require('mediaxml/document')
class Channel extends Node {
get name() {
return this.query('[name="name"]:first:text') || null
}
}
class CustomDocument extends Document {
get channels() {
const results = this.query('[name="channel"]')
return (results ? [].concat(results) : []).map((r) => Channel.from(r))
}
}
const document = CustomDocument.from(`
<package>
<channel>
<name>Channel A</name>
</channel>
<channel>
<name>Channel B</name>
</channel>
</package>
`)
console.log(document.channels)
console.log(document.query('channels.name'))
Query User Guide
Query Preprocessor
Queries are preprocessed to handle special syntax as sugar on top of JSONata syntax.
Selectors
:children([index[, count]])
Selects children from an object that has a children
field value.
Values from the children
array can be sliced optionally when called
with functional syntax children(start, count)
.
$:children(2, 4) /** slices 4 children from the root starting at index 2 */
[:]attr([name])
Selects an attribute value of by name from an object that has an
attribute
field value.
**:attr(url) /** selects "url" attribute from any node */
:text
Selects text value from an object that has a text
field value.
**:text /** selects text value from any node */
Ordinals
Ordinals as selectors like :first
and :last
can be used to
reference the first and last elements in an array. Ordinals like
:second
, :third
, :fourth
all the way to up :tenth
can be used to
reference their corresponding element in an array.
:first
Selects the first element in an array.
$:children:first /** This is the same as $.children[0] */
:second
Selects the second element in an array.
$:children:second /** This is the same as $.children[1] */
:third
Selects the third element in an array.
$:children:third /** This is the same as $.children[2] */
:fourth
Selects the fourth element in an array.
$:children:fourth /** This is the same as $.children[3] */
:fifth
Selects the fifth element in an array.
$:children:fifth /** This is the same as $.children[4] */
:sixth
Selects the sixth element in an array.
$:children:sixth /** This is the same as $.children[5] */
:seventh
Selects the seventh element in an array.
$:children:seventh /** This is the same as $.children[6] */
:eighth
Selects the eighth element in an array.
$:children:eighth /** This is the same as $.children[7] */
:ninth
Selects the ninth element in an array.
$:children:ninth /** This is the same as $.children[8] */
:tenth
Selects the tenth element in an array.
$:children:tenth /** This is the same as $.children[9] */
:last
Selects the last element in an array.
$:children:last /** This is the same as $.children[-1] */
Operators
is
Comparison operator that compares values in a variety of ways.
is [not] <string|array|number|boolean|object|function>
Compares value to a primitive type.
/** finds all nodes with an url attribute that is a non-empty string */
**[attr(url) is string and attr(url) is not empty]
is [not] <null|true|false|NaN|Infinity>
Compares value to a constant type.
/** finds all nodes with an role attribute that is not null */
**[attr(role) is not null]
is [not] <Date|Document|Node|Fragment|Text>
Compares value to a class type.
/** finds any value that is a `Date` instance */
**[is Date]
is [not] <expr>
Compares value to right hand expression.
/** finds any node where the url attribute is not a "bad url" */
**[attr(url) is not "bad url"]
as
Casting operator that can cast values to a variety of other values.
as <array|boolean|float|function|int|number|object|string>
Cast a value to a primitive type.
123 as boolean /** true */
456 as string /** '456' */
123.456 as int /** 123 */
'0.12300' as float /** 0.123 */
'abc' as array /** ['a', 'b', 'c'] */
123 as string as array /** [] */
as <false|true|NaN|null>
Cast a value to a constant type.
123 as false /** false */
"foo" as true /** true */
0 as null /** null */
123 as NaN /** NaN */
as <Date|Document|Fragment|Node|Text>
Cast a value to an instance type.
"2020-04-20" as Date /** 2020-04-20T00:00:00.000Z */
as camelcase
Cast a value to a camel cased string.
"hello world" as camelcase /** helloWorld */
as pascalcase
Cast a value to a pascal cased string.
"hello world" as camelcase /** HelloWorld */
as snakecase
Cast a value to a snake cased string.
"hello world" as camelcase /** hello_world */
as json
Cast a value to a parsed JSON.
'{"hello": "world"}' as json /** { hello: 'world' } */
as keys
Cast a value to an enumeration of its keys.
({"hello": true, "world": false}) as keys /** ['hello', 'world'] */
as sorted
Cast a value to a sorted array.
([3, 2, 1, 'a', 'b']) as sorted /** [1, 2, 3, 'a', 'b'] */
as reversed
Cast a value to a reversed string or array.
'123cba' as reversed /** 'abc321' */
as unique
Cast a value to an array or string with unique elements
'aabbccdd' as unique /** 'abcd' */
as tuple
Cast a value to tuple with key
and value
pairs.
({"hello": "world"}) as tuple /** { key: 'hello', value: 'world' } */
let <key> = <value>
Sets a global variable for the execution of the query.
let a = 1;
let b = 2;
let c = $a + $b; /** 3 */
let key = 'd';
let $key = $c + 2; /** 5 */
print $d /** 5 */
[target] has <subject>
Check if <subject>
is a property of target
. Optionally, this
operator can be used in a query with the target
omitted as it is
implicitly inferred.
({ "foo": "bar" }) has "foo" // true
**[attributes has url] // returns all nodes that have a "url" attribute
**:attributes[has url] // returns all attributes that have a "url" field
typeof <target>
Computes the type of target
as a string.
typeof "foo" // 'string'
typeof ({}) // 'object'
typeof 123 // 'number'
import <URI>
Import a XML file or query string from a given URI
. A valid URI
can
be a HTTP(S) resource or a file path (optionally specified with
file://
). The import
operator requires a runtime loader. A runtime
loader is given for the mxml(1)
command.
import 'https://raw.githubusercontent.com/little-core-labs/mediaxml/master/example/mrss/feed.xml'
**[is text and is not empty]
[target] contains <data>
Checks if data
is contained by target
.
Casting
Types can be casted to and from a variety of types.
Primitives
'123' as int // 123
'123.456' as int // 123
0 as boolean // false
1 as boolean // true
123 as string // '123'
123 as int<16> // 291
'abc' as array // ['a', 'b', 'c']
Specials
$now() as Date // 2021-03-08T19:54:26.205Z
'{"hello": "world"}' as json // { hello: 'world' }
this as json // { name: '#empty', text: '', attributes: {}, children: [] }
let $xml = '<rss><channel><title>hello</title></channel></rss>'
$xml as Node
/**
* <rss>
* <channel>
* <title>hello</title>
* </channel>
* </rss>
*/
String Casing
'hello world' as CamelCase // helloWorld
'hello world' as SnakeCase // hello_world
'hello world' as PascalCase // HelloWorld
Transforms
'fbdeca' as sorted // 'abcdef'
([3,2,1]) as sorted // [3, 2, 1]
({"d": 1, "c": 2, "b": 3, "a": 4}) as json as sorted
/**
* {
* a: 4,
* b: 3,
* c: 2,
* d: 1
* }
*/
this as text // `<#empty />`
JSONata Function Bindings
In addition to the already built-in JSONata functions , the following functions are registered as JSONata syntax functions and can be used in the query string.
Reflection
This section contains functions for reflecting runtime values such as class constructor names or instance primitive type names.
$typeof(<j-:s>)
Returns the type of input as a string. This function will return array
for
arrays, date
for Date
instances, otherwise typeof input
.
$typeof("string") // string
$typeof(123) // number
$classConstructorName(<j-:s>)
Returns the class constructor name for given input. This function will always return a string.
Transform
This section contains functions for transforming input into a new output.
$tuple(<j-:a>)
Convert input into {key: ..., value: ...}
pairs.
mxml (epg.xml)> **:attrs.$tuple() /** map all attributes to the `$tuple()` */
{
key: 'source-info-url',
value: 'http://www.schedulesdirect.org/'
}
{
key: 'source-info-name',
value: 'Schedules Direct'
}
...
$keys(<j-:a>)
Returns computed keys of input as an array.
$json(<j-j?:j>)
Converts input into a plain JSON object (parsed).
$array(<j-:a>)
Converts input to an array.
$date(<j-:o>)
Converts input into a date.
$int(<j-j?:n>)
Converts input into an integer.
$float(<j-j?:n>)
Converts input into a float.
$boolean(<j-:b>)
Converts input into a boolean.
$string(<j-j?:s>)
Converts input into a string.
$true(<j-:b>)
Returns true for any input.
$false(<j-:b>)
Returns false for any input.
Strings
$camelcase(<s-:s>)
Converts input string to camelcase.
$length(<j-:n>)
Returns the length of input string.
Arrays
$concat(<a<j->:a>)
Returns concatenated variable input as an array.
$length(<j-:n>)
Returns the length of input array.
$unique(<j-:a>)
Returns input array with only unique elements.
$slice(<j-:a>)
Returns a slice of an array or parser node.
$join(<a-s?:s>)
Returns an array joined by a given delimiter (default: ",").
$isArray(<j-:b>)
Returns true if input is an array, otherwise false.
Utility
$print(<j-:l>)
Prints variable input to stdout.
$now(<j-:n>)
Returns the UNIX Epoch in milliseconds.
Command Line Interface
The mediaxml
module ships with a command line interface program for running
queries targeted at an XML document. The program is called mxml
and
can be invoked like mxml <filename> <query>
. The filename
can be a
fully qualified URL or a path to a file on disk.
Usage
usage: mxml [-hiDV] [options] <filename> [query]
options:
-h, --help Show this message
-i, --inspect Show inspected output
-D, --debug Show debug output
-V, --version Show program version
arguments:
<filename> Path to XML file (required)
[query] Query in JSONata syntax on resulting model [optional]
examples:
## read ADI metadata
mxml ./tvshow.xml 'adi:children[name = "Metadata"]'
## look for ADI3 "Movie" assets
mxml ./movie.xml 'adi3:children[`xsi:type` = "content:MovieType"]'
Examples
Query <App_Data />
nodes that are children of the first <Metadata />
node in an ADI document.
$ mxml ./tvshow.xml ':root :children[name = "Metadata"]:first :children[name = "App_Data"]'
Query all <title />
node text values in all <item />
nodes in a RSS
or mRSS document.
$ mxml ./feed.rss ':root :children[name = "item"] :children[name = "title"] :text'
Start a repl session with debug mode enabled.
$ mxml ./feed.rss --debug mxml (feed.xml)>
REPL Mode
The mxml
command can also be used to initiate a repl session
for interactively querying the document object module of an XML
document.
$ mxml ./feed.rss
mxml (feed.xml)> :root:name /** query the name of the root node */
rss
query: 42.626ms
mxml (feed.xml)> $unique(**[is node]:name) /** query the name of all nodes in the document */
rss
channel
title
link
language
pubDate
lastBuildDate
managingEditor
description
image
url
height
width
atom:link
item
guid
media:category
media:content
media:title
media:description
media:thumbnail
media:credit
media:copyright
mxml (feed.xml)>
See Also
REPL
The mediaxml
module ships with a command line program that provides a
repl
for interactive sessions to explore the contents of an XML file and its
corresponding node hierarchy.
To start a session, simply run the mxml
command specifying a
filename
. The filename
can be a fully qualified URL, or a relative
path to a file. The file is loaded and parsed before the session is
started.
Debug output can be enabled with the --debug
flag upon starting that
program.
Starting a new session should look like:
$ mxml feed.rss mxml (feed.xml)>
The smallest query we can run is the :root
query (or $
in JSONata
syntax) which should yield the root of the document.
mxml (feed.xml)> :root
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title>Calm Meditation</title>
...
The attributes of the root node can be queried with the :attr
selector.
mxml (feed.xml)> :root:attr
ParserNodeAttributes {
'xmlns:atom': 'http://www.w3.org/2005/Atom',
'xmlns:media': 'http://search.yahoo.com/mrss/',
version: 2
}
query: 9.114ms
An attribute value can be queried by specifying the name of the
attribute as an argument to the :attr(name)
selector.
mxml (feed.xml)> :root:attr(xmlns:media) http://search.yahoo.com/mrss/ query: 41.854ms mxml (feed.xml)> :root:attr(xmlns:atom) http://www.w3.org/2005/Atom query: 3.631ms mxml (feed.xml)> :root:attr(version) 2 query: 4.891ms
API
The mediaxml
module exports a variety of high level modules documented in the
following sections such as mediaxml/adi
, and mediaxml/xmltv
and more.
const adi = require('mediaxml/adi')
const adi3 = require('mediaxml/adi3')
const mrss = require('mediaxml/mrss')
const rss = require('mediaxml/rss')
const xmltv = require('mediaxml/xmltv')
adi
Example
const adi = require('mediaxml/adi')
const fs = require('fs')
const stream = fs.createReadStream('./package.xml')
const document = adi.createDocument(stream)
document.ready(() => {
console.log(document.metadata)
for (const asset of document.asset.assets) {
console.log(asset.metadata, asset.appData)
}
})
static
adi.Document
new Document(input: (adi.Document | Parser | String | ReadableStream), opts: Object?)
A class that represents an ADI document with special entity access.
Example
const fs = require('fs')
const stream = fs.createReadStream('./package.xml')
const document = Document.from(stream)
document.ready(() => {
console.log(document.metadata)
console.log(document.asset)
})
adi.Metadata
new Metadata(document: Document, node: ParserNode)
A metadata entity found in ADI documents.
Parameters
document: Document
:node: ParserNode
:
adi.AMS
new AMS(document: Document, node: ParserNode)
An AMS (Asset Management Service) entity found in ADI documents.
Parameters
document: Document
:node: ParserNode
:
adi.AppData
new AppData(document: Document, node: ParserNode)
An AppData entity found in ADI documents.
Parameters
document: Document
:node: ParserNode
:
adi.Content
new Content(document: Document, node: ParserNode)
A content entity found in ADI documents.
Parameters
document: Document
:node: ParserNode
:
adi3
A module to provide atomic classes for working with ADI3 documents.
Example
const adi3 = require('mediaxml/adi3')
const fs = require('fs')
const stream = fs.createReadStream('./package.xml')
const document = adi3.createDocument(stream)
document.ready(() => {
for (const asset of document.assets) {
}
})
static
adi3.Document
new Document(input: (Document | Parser | String | ReadableStream), opts: Object?)
An extended Document
that represents an ADI3 document with special
entity access.
Example
const fs = require('fs')
const stream = fs.createReadStream('./package.xml')
const document = Document.from(stream)
document.ready(() => {
console.log(document.metadata)
console.log(document.asset)
})
adi3.Asset
new Asset(document: Document, node: ParserNode)
An asset entity found in ADI3 documents.
Parameters
document: Document
:node: ParserNode
:
adi3.SubscriberViewLimit
new SubscriberViewLimit(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.AlternateId
new AlternateId(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.Extension
new Extension(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.EncryptionInfo
new EncryptionInfo(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.CopyControlInfo
new CopyControlInfo(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.Rating
new Rating(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.DistributorRoyaltyInfo
new DistributorRoyaltyInfo(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.StudioRoyaltyInfo
new StudioRoyaltyInfo(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.LocalizableTitle
new LocalizableTitle(document: Document, node: ParserNode)
Parameters
document: Document
:node: ParserNode
:
adi3.Actor
new Actor(document: Document, node: ParserNode)
A container for actor data.
Parameters
document: Document
:node: ParserNode
:
adi3.Director
new Director(document: Document, node: ParserNode)
A container for director data.
Parameters
document: Document
:node: ParserNode
:
adi3.Chapter
new Chapter(document: Document, node: ParserNode)
A container for chapter heading and time code data.
Parameters
document: Document
:node: ParserNode
:
rss
A module to provide atomic classes for working with RSS documents.
Example
const rss = require('mediaxml/rss')
const fs = require('fs')
const stream = fs.createReadStream('./feed.rss')
const document = rss.createDocument(stream)
document.ready(() => {
const { channel } = document
console.log(channel.name, channel.description)
for (const item of channel.items) {
console.log(item)
}
})
static
rss.Document
new Document(input: (Document | Parser | String | ReadableStream), opts: Object?)
An extended Document
that represents a RSS document with special
entity access.
Example
const fs = require('fs')
const stream = fs.createReadStream('./feed.rss')
const document = Document.from(stream)
document.ready(() => {
console.log(document.channel.items)
})
rss.Channel
new Channel(document: Document, node: ParserNode)
A channel entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
rss.TextInput
new TextInput(document: Document, node: ParserNode)
A textInput entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
rss.Image
new Image(document: Document, node: ParserNode)
An image entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
rss.Category
new Category(document: Document, node: ParserNode)
A category entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
rss.Item
new Item(document: Document, node: ParserNode)
An item entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
rss.Source
new Source(document: Document, node: ParserNode)
A source entity found in RSS documents.
Parameters
document: Document
:node: ParserNode
:
mrss
A module to provide atomic classes for working with mRSS documents.
Example
const mrss = require('mediaxml/mrss')
const fs = require('fs')
const stream = fs.createReadStream('./feed.rss')
const document = mrss.createDocument(stream)
document.ready(() => {
const { channel } = document
console.log(channel.name, channel.description)
for (const item of channel.items) {
console.log(item.mediaContent)
}
})
See
static
mrss.Document
new Document(input: (Document | Parser | String | ReadableStream), opts: Object?)
An extended Document
that represents a mRSS document with special
entity access.
mrss.Channel
new Channel(document: Document, node: ParserNode)
A channel entity found in MRSS documents.
Parameters
document: Document
:node: ParserNode
:
mrss.Item
new Item(document: Document, node: ParserNode)
An item entity found in MRSS documents.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaGroup
new MediaGroup(document: Document, node: ParserNode)
A media group represents a grouping of media content found in an item
Parameters
document: Document
:node: ParserNode
:
mrss.MediaContent
new MediaContent(document: Document, node: ParserNode)
A media content container for describing content found in an item or media group
Parameters
document: Document
:node: ParserNode
:
mrss.MediaPlayer
new MediaPlayer(document: Document, node: ParserNode)
A media player container for describing the parameters needed for a media player to play or view a media content object.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaRating
new MediaRating(document: Document, node: ParserNode)
A media rating container to store the scheme and rating value.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaTitle
new MediaTitle(document: Document, node: ParserNode)
A media title container to store the type and text value.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaDescription
new MediaDescription(document: Document, node: ParserNode)
A media description container to store the type and text value.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaThumbnail
new MediaThumbnail(document: Document, node: ParserNode)
A media thumbnail container to store the image width, height, url and a NPT (Normal Play Time) timecode that corresponds to the media content this thumbnail is associated with.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaCategory
new MediaCategory(document: Document, node: ParserNode)
A media category container to store the category scheme and label
Parameters
document: Document
:node: ParserNode
:
mrss.MediaHash
new MediaHash(document: Document, node: ParserNode)
A media hash container to store the hash algorithm and value.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaCredit
new MediaCredit(document: Document, node: ParserNode)
A media credit container to store the credit scheme, role, and value.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaCopyright
new MediaCopyright(document: Document, node: ParserNode)
A container for media copyright information.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaText
new MediaText(document: Document, node: ParserNode)
A container for transcript text.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaRestriction
new MediaRestriction(document: Document, node: ParserNode)
A container for a media restriction.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaCommunity
new MediaCommunity(document: Document, node: ParserNode)
A container for media community information such as star ratings, statistics, and tags.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaEmbed
new MediaEmbed(document: Document, node: ParserNode)
A media container for embedded media.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaEmbedParameters
new MediaEmbedParameters(document: Document, node: ParserNode)
A container for reading media embed parameters.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaStatus
new MediaStatus(document: Document, node: ParserNode)
A container for describing media status.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaPrice
new MediaPrice(document: Document, node: ParserNode)
A container for describing the price of media content.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaLicense
new MediaLicense(document: Document, node: ParserNode)
A container for a media license backed by a URL.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaSubTitle
new MediaSubTitle(document: Document, node: ParserNode)
A container for a subtitle file.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaPeerLink
new MediaPeerLink(document: Document, node: ParserNode)
A container for a peerlink.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaRights
new MediaRights(document: Document, node: ParserNode)
A container for media rights.
Parameters
document: Document
:node: ParserNode
:
mrss.MediaLocation
new MediaLocation(document: Document, node: ParserNode)
A container for media location data.
Parameters
document: Document
:node: ParserNode
:
xmltv
A module to provide atomic classes for working with XMLTV documents.
Example
const xmltv = require('mediaxml/xmltv')
const fs = require('fs')
const stream = fs.createReadStream('./epg.xml')
const document = xmltv.createDocument(stream)
document.ready(() => {
console.log(document.channels)
for (const programme of document.programmes) {
console.log(programme.title, programme.start, programme.stop)
}
})
See
static
xmltv.Document
new Document(input: (Document | Parser | String | ReadableStream), opts: Object?)
An extended Document
that represents an XMLTV document with special
entity access.
Example
const fs = require('fs')
const stream = fs.createReadStream('./epg.xml')
const document = Document.from(stream)
document.ready(() => {
console.log(document.channels)
console.log(document.programmes)
})
xmltv.LocalizedTextEntity
new LocalizedTextEntity(document: Document, node: ParserNode)
Base class for a localizable (lang="en) entity.
Parameters
document: Document
:node: ParserNode
:
xmltv.DisplayName
new DisplayName(document: Document, node: ParserNode)
A container for a display name.
Parameters
document: Document
:node: ParserNode
:
xmltv.Title
new Title(document: Document, node: ParserNode)
A container for a title.
Parameters
document: Document
:node: ParserNode
:
xmltv.SubTitle
new SubTitle(document: Document, node: ParserNode)
A container for a subtitle.
Parameters
document: Document
:node: ParserNode
:
xmltv.Description
new Description(document: Document, node: ParserNode)
A container for a description.
Parameters
document: Document
:node: ParserNode
:
xmltv.Category
new Category(document: Document, node: ParserNode)
A container for a category.
Parameters
document: Document
:node: ParserNode
:
xmltv.Language
new Language(document: Document, node: ParserNode)
A container for a language.
Parameters
document: Document
:node: ParserNode
:
xmltv.OriginalLanguage
new OriginalLanguage(document: Document, node: ParserNode)
A container for an original language.
Parameters
document: Document
:node: ParserNode
:
xmltv.Icon
new Icon(document: Document, node: ParserNode)
A container for an icon.
Parameters
document: Document
:node: ParserNode
:
xmltv.AudioDescription
new AudioDescription(document: Document, node: ParserNode)
A container for an audio description for a programme.
Parameters
document: Document
:node: ParserNode
:
xmltv.VideoDescription
new VideoDescription(document: Document, node: ParserNode)
A container for a video description for a programme.
Parameters
document: Document
:node: ParserNode
:
xmltv.StarRating
new StarRating(document: Document, node: ParserNode)
A container for a star rating for a programme.
Parameters
document: Document
:node: ParserNode
:
xmltv.Rating
new Rating(document: Document, node: ParserNode)
A container for a programme rating.
Parameters
document: Document
:node: ParserNode
:
xmltv.Credits
new Credits(document: Document, node: ParserNode)
A container for programme credits such as directors, producers, actor, and more.
Parameters
document: Document
:node: ParserNode
:
xmltv.EpisodeNumber
new EpisodeNumber(document: Document, node: ParserNode)
A container for an episode number value and the system used to determine it.
Parameters
document: Document
:node: ParserNode
:
xmltv.Channel
new Channel(document: Document, node: ParserNode)
A channel entity found in XMLTV documents.
Parameters
document: Document
:node: ParserNode
:
Core
The mediaxml
module exports a variety of core modules documented in the
following sections such as mediaxml/parser
, mediaxml/query
,
mediaxml/document
, and more.
const document = require('mediaxml/document')
const entity = require('mediaxml/entity')
const normalize = require('mediaxml/normalize')
const parser = require('mediaxml/parser')
const query = require('mediaxml/query')
document
A core module for working with and building XML documents. The interfaces provided by this module are porcelain and be used instead of the parser API.
Example
const { createDocument, createNode } = require('mediaxml/document')
const assets = []
const document = createDocument(`
<?xml version="1.0"?>
<package>
<assets />
</package>
`)
assets.push(createNode('asset', {
name: 'first',
url: 'https://example.com/first.mp4'
}))
assets.push(createNode('asset', {
name: 'second',
url: 'https://example.com/second.mp4'
}))
document.query('[name="assets"]').append(...assets)
console.log(document)
// <package>
// <assets>
// <asset name="first" url="https://example.com/first.mp4" />
// <asset name="second" url="https://example.com/second.mp4" />
// </assets>
// </package>
const urls = document.query('**[name="asset"]:attr(url)')
console.log(urls)
// ParserNodeFragment(2) [
// 'https://example.com/first.mp4',
// 'https://example.com/second.mp4'
// ]
See
static
document.Node
new Node(name: String, attributes: Object?, depth: Number?, opts: Object?)
An abstract document node.
See
document.AbstractDocument
new AbstractDocument(parser: Parser, opts: Object?)
An abstract document object model.
Parameters
parser: Parser
:opts: Object?
:
document.Document
new Document(parser: Parser, opts: Object?)
An abstract document object model for XML.
Parameters
parser: Parser
:opts: Object?
:
document.createDocument
createDocument(args: ...any): Document
Factory for creating Document
instances.
Parameters
args: ...any
:
Returns
entity
A module for the base Entity
used as a base class for
various porcelain classes.
Example
const { normalizeValue } = require('mediaxml/normalize')
const { Entity } = require('mediaxml/entity')
class Programme extends Entity {
get channel() {
return this.attributes.channel
}
get start() {
return normalizeValue(this.attributes.start)
}
get stop() {
return normalizeValue(this.attributes.stop)
}
}
const node = document.query('[name="programme"]')
const programme = Programme.from(document, node)
console.log(programme.channel, programme.start, programme.stop)
static
entity.Entity
new Entity(document: Document, node: ParserNode)
Base entity used as a base class for various porcelain classes.
Parameters
document: Document
:The document this entity node is owned bynode: ParserNode
:The node this entity represents a view over
Example
const { Entity } = require('mediaxml/entity')
class Programme extends Entity {
get channel() {
return this.attributes.channel
}
}
const node = document.query('[name="programme"]')
const programme = Programme.from(document, node)
console.log(programme.channel)
normalize
A module that provides various normalization functions.
Example
const { normalizeKey, normalizeValue, normalizeAttributes } = require('mediaxml/normalize')
console.log(normalizeKey('Asset_ID'))
// 'assetId'
console.log(normalizeValue('2021-01-23T18:12:42.963Z'))
// Date (2021-01-23T18:12:42.963Z)
console.log(normalizeAttributes({ Time_Code: '00:01.5-01:00' }).timeCode)
// Timecode (00:00:01.5-00:01:00) {
// start: Time (00:00:01.5) { value: 1.5 },
// stop: Time (00:01:00) { value: 60 }
// }
static
normalize.normalizeValue
normalizeValue(value: any?): any?
Normalize a value from a string or mixed input.
Parameters
value: any?
:
Returns
any?
Example
console.log(normalizeValue())
// null
Example
console.log(normalizeValue(true))
// true
Example
console.log(normalizeValue(false))
// true
Example
console.log(normalizeValue('foo'))
// 'foo'
Example
console.log(normalizeValue('123.45'))
// 123.45
Example
console.log(normalizeValue('2021-01-23T18:12:42.963Z'))
// Date (2021-01-23T18:12:42.963Z)
Example
console.log('NPT Timecode', normalizeValue('00:45))
// Timecode (00:00:45-) { start: Time (00:45:32) { value: 2732 }, ... }
Example
console.log('SMPTE Timecode', normalizeValue('00:45:32;00'))
// Timecode { frameRate: 29.97, dropFrame: true, .... }
Example
console.log('ISO-8601 Duration', normalizeValue('P1Y2M3DT4H5M6S'))
// { years: 1, months: 2, days: 3, ... }
normalize.normalizeAttributes
normalizeAttributes(attributes: any, opts: Object?, attribute: Object): Object
Normalize attribute key-value pairs.
Parameters
Returns
Example
const attrs = normalizeAttributes({ Time_Code: '00:01.5-01:00' })
console.log(attrs.timeCode)
// Timecode (00:00:01.5-00:01:00) {
// start: Time (00:00:01.5) { value: 1.5 },
// stop: Time (00:01:00) { value: 60 }
// }
normalize.normalizeKey
normalizeKey(key: String, opts: Object?): String
Normalize key.
Parameters
key: String
:Key to normalize
Returns
Example
console.log(normalizeKey('Asset_ID'))
// 'assetId'
Example
console.log(normalizeKey('Asset_ID'), { preserveConsecutiveUppercase: true })
// 'assetID'
normalize.normalizeAttributeKey
normalizeAttributeKey(key: String, opts: Object?): String
Normalize attribute key.
Parameters
key: String
:Key to normalize
Returns
Example
console.log(normalizeAttributeKey('Provider_ID'))
// 'providerID'
Example
console.log(normalizeAttributeKey('Provider_ID'), { preserveConsecutiveUppercase: false })
// 'providerId'
See
normalizeKey
parser
The core parsing API for the MediaXML module that creates a document object model for a parsed XML file with a robust query API built on top of JSONata.
Example
const { Parser } = require('mediaxml/parser')
const fs = require('fs')
const stream = fs.createReadStream('package.xml') // ADI
const parser = Parser.from(stream)
parser.then(() => {
const { rootNode } = parser
const assets = parser.query('**[name="asset"]') // get all '<Asset />' nodes
})
static
parser.ParserNodeAttributes
new ParserNodeAttributes(attributes: Object?, opts: Object?)
A simple container for a ParserNode
instance attributes.
parser.ParserNodeText
new ParserNodeText(text: String, opts: any, depth: any)
A container for a text.
Parameters
text: String
:opts: any
:depth: any
:
parser.ParserNodeFragment
new ParserNodeFragment(attributes: Object?, opts: Object?)
A container for a collection of ParserNode
instances not represented by a root
ParserNode
instance.
parser.ParserNode
new ParserNode(name: String, attributes: Object?, depth: Number?, opts: Object?)
A container for a parsed XML node with references to its parent node and children.
Example
const metadata = ParserNode.from('Metadata')
const appData = ParserNode.from('App_Data', { app: 'SVOD', name: 'Type', value: 'title' })
metadata.appendChild(appData)
console.log(metadata)
// <Metadata>
// <App_Data app="SVOD" name="Type" value="title" />
// </Metadata>
parser.ParserState
new ParserState(stack: Array?)
A simple stack to store parser state.
Parameters
stack: Array?
:
parser.ParserOptions
new ParserOptions(opts: Object?)
Options with defaults for a ParserHandler
instance
Parameters
opts: Object?
:
query
Module exports.
static
query.cache
cache: Map
An internal cache used to cache compiled queries.
Example
const { cache } = require('mediaxml/query')
// clear the query cache of all entries (compiled expressions, etc)
cache.clear()
query.Imports
new Imports(opts: Object)
An extended Map of imports with an abstract load()
method.
Parameters
opts: Object
:
query.Assignments
new Assignments()
An extended Map of key-value assignments for global variables.
query.Context
new Context(opts: Object)
Query context object that is a container for imports, global variables, query target, and more.
Parameters
opts: Object
:
query.Expression
new Expression(context: any, string: String, opts: Object?)
Query expression container. Query transforms and bindings are applied here.
query.Transforms
new Transforms(context: Context, transforms: ...any)
Query transform container to apply many transforms to an input.
Parameters
context: Context
:transforms: ...any
:
query.Bindings
new Bindings(context: Context, entries: ...any)
Query bindings container
Parameters
context: Context
:entries: ...any
:
query.query
query(node: ParserNode?, queryString: String?, opts: Object?): (ParserNode | ParserNodeFragment | String | any)?
Query the document object model represented by a node using "JSONata" query syntax with special selector syntax for working with {ParserNode} instances.
JSONata functions
Parameters
node: ParserNode?
:The parser node to queryopts: Object?
:Query optionsopts.model: Object? (={})
:An optional model to query, instead of one derived from the inputnode
opts.bindings: Object? (=node.options.bindings)
:Bindings to use instead of the ones derived from the inputnode
opts.assignments: Object??
:A key-value object of variable assignments. This function will modify this object.opts.imports: Map??
:A map of existing imports. This function will modify this map.opts.load: Function??
:An import loader function. This function must be given if queries use theimport <path|URL>
statement.
Returns
(ParserNode | ParserNodeFragment | String | any)?
Example
// select first node with node name "channel"
const channel = query(node, '[name="channel"]:first')
Example
// select the 'href' attribute value from the first child with a node name
// of "atom:link" from the first "channel" node
const atom = query(node, '[name="channel"]:first:children:first[name="atom:link"]:attr(href)')
Example
// select the text of the first node with a name that matches the
`/^offer:BillingId$/i` regular expression
const billingId = query(node, '[name ~> /^offer:BillingId$/i]:first:text')
fragment
A module that provides a container for fragment nodes.
Example
const { Fragment } = require('mediaxml/fragment')
const { Text } = require('mediaxml/fragment')
const fragment = Fragment.from([Text.from('hello'), Text.from('world'), Text.from('')])
const textNodes = node.query('**[ is text and is not empty ]')
validate
A module to provide XML validation.
Example
const { validate } = require('mediaxml/validate')
try {
validate(xml)
} catch (err) {
// handle validation error
}
static
validate.ValidationError
new ValidationError(code: String, message: String, opts: Object?)
A container for a validation error derived from a SyntaxError
class.