Sage XML Show Information export
The XML show information generated by the Sage WebServer and the SageRecordingsXmlGenerator follows the format as specified by the sageshowinfo.DTD document type definition. The DTD documents the XML format in detail.
The following is an annotated version of an xml file generated for a single recording according to this format. The current version is v1.1.
For multiple recordings/airings/favorites, there will be multiple child elements of the channelList, favoriteList and showList elements.
All dates are in ISO 8601 date+time format specified for UTC/GMT time zone.
A Java ISO 8601 parser is avalable in cvs, and is included in the nielm_sagexmlinfo.jar file.
The API for generating these XML files is available for use by other Java plugins, and can also be called from STVs.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE sageShowInfo PUBLIC "-//NIELM//DTD SAGESHOWINFO XML 1.2//EN" "http://sageplugins.sourceforge.net/nielm_modules/sagexmlinfo/sageshowinfo_1_2.dtd">
<sageShowInfo version="1.2">
<channelList>
<channel channelId="6162">
<--
The channel element contains information abaout a channel
The channel ID is sage's internal channel identifier
and will be used to reference this channel in airing elements
-->
<channelName>BBC1</channelName>
<channelDescription>BBC ONE London and South East</channelDescription>
<channelNetwork>BBC</channelNetwork>
<channelNumber>2</channelNumber>
</channel>
</channelList>
<favoriteList>
<favorite favoriteId="1648157">
<--
The favorite element contains the definition of a favorite
The favorite ID is sage's internal favorite identifier,
and will be used to reference this favorite in airing elements
-->
<title>Hustle</title> <-- for title favorites -->
<-- category/people/keyword favorites would use other elements -- see DTD -->
<channelName>BBC1</channelName> <-- only match shows on this channel -->
<timeslot>Thursday 19:00</timeslot> <-- only match shows on this timeslot -->
<firstRun/> <-- This favorite will match first-run shows -->
<reRun/> <-- This favorite will match re-run shows
(with firstRun, means that both first-run and re-runs will be selected) -->
<quality>Default</quality> <-- Recording quality for this favorite -->
<startPadding>300</startPadding> <-- seconds before -->
<stopPadding>300</stopPadding> <-- seconds after -->
<keepAtMost>5</keepAtMost> <-- keep maximum 5 recordings -->
<autoDelete/> <-- Favorite can be auto-deleted -->
</favorite>
</favoriteList>
<showList>
<--
The show element defines a Show. The (optional) epgId is the ID as supplied
by the listings provider -- if Zap2It, this ID can be found on their
website. If it is left blank, a random epgID will be generated on import
A show can have many Airings (each airing on a different channel/timeslot)
Apart from the title element, all Show elements are optional
-->
<show epgId="EP1a1eb45e">
<title>My Show Title</title> <-- required -->
<episode>Episode</episode>
<duration>3600</duration> <-- Show duration in seconds -->
<category>Category</category>
<subCategory>Subcategory</subCategory>
<description>This is a short description of the show</description>
<rating>PG</rating> <-- MPAA rating -->
<advisoryList>
<-- list of Advisories: can be any of:
"Graphic Violence" | "Violence" | "Mild Violence"
"Graphic Language" | "Language" | "Adult Situations"
"Strong Sexual Content" | "Nudity" | "Brief Nudity" |"Rape"
or the local language equivalent
-->
<advisory>Violence</advisory>
<advisory>Mild Violence</advisory>
</advisoryList>
<peopleList>
<--
list of people with roles.
supported roles are:
"Actor" | "Lead_Actor" | "Supporting_Actor" |
"Actress" | "Lead_Actress" | "Supporting_Actress" |
"Guest" | "Guest_Star" | "Director" | "Producer" |
"Writer" | "Choreographer" | "Sports Figure" | "Coach" |
"Host" | "Executive_Producer" | "Artist"
-->
<person role="Actor">Denzel Washington</person>
<person role="Actor">Meryl Streep</person>
<person role="Actor">Liev Schreiber</person>
<person role="Actor">Jeffrey Wright</person>
<person role="Actor">Kimberly Elise</person>
<person role="Director">Jonathan Demme</person>
</peopleList>
<year>2006</year>
<language>English</language>
<originalAirDate>2006-03-21T17:00:00.00Z</originalAirDate>
<--
The last elements of a Show are 0 or more airings
detailing when a show is broadcast on which channel
An airing can optionally reference a channel by ID
An airing can optionally reference a favorite
The optional sageDbID is the internal ID used by Sage to reference this airing, and
is normally found in the file name.
The StartTime (required) is in ISO 8601 format, and always expressed in GMT.
Duration (required) is in seconds
-->
<airing
channelId="6162"
favoriteId="1648157"
duration="3600"
sageDbId="246646"
startTime="2006-03-21T17:00:00.00Z">
<-- Parental Ratings for the airing may be set here -->
<parentalRating>TV14</parentalRating>
<--
An Airing can have several flags: watched, don't like, a manual recording
These flags are included here if set
-->
<isHDTV/>
<stereo/>
<subtitled/>
<closedCaptioned/>
<sap/> <-- Secondary Audio Program -->
<--
The optional premierFinale element may be one of:
"Premiere" "Season_Premiere" "Series_Premiere" "Channel_Premiere"
"Season_Finale" "Series_Finale"
-->
<premierFinale>Season_Premiere</premierFinale>
<--
An Airing may have a media file associated with it
The sageDbID is the internal ID used by Sage to reference this mediaFile.
The StartTime is in ISO 8601 format, and always expressed in GMT.
If not specified, StartTime and Duration are taken from the Airing
The Type may be one of: TV | ImportedVideo | ImportedDVD | Music | Picture
-->
<mediafile
duration="3567"
sageDbId="246647"
startTime="2006-03-21T17:00:00.00Z"
type="TV">
<archived/>
<--
A mediafile may be made up of multiple file segments, which are listed here
If not specified, StartTime and Duration are taken from the MediaFile element
Again, the StartTime is in ISO 8601 format, and always expressed in GMT.
-->
<segmentList>
<segment
duration="3567"
filePath="E:\Video\MyShowTitle-Episode-246646-0.mpg"
startTime="2006-03-21T17:00:00.00Z"/>
</segmentList>
</mediafile>
</airing>
</show>
</showList>
</sageShowInfo>
Note to programmers
If you attempt to parse this file using a Validating XML parser, it will attempt to download the DTD from the URL specified in the doctype. This is generally a bad idea -- if the SF website is down, or you do not have internet access, parsing will fail.
To solve this, an application should keep a local copy of the DTD, and tell the parser to use the local copy in preference to the on-line copy when parsing.
This is done by telling the parser to use a custom Entity Resolver. In Java the following code can be used as a template (from SageXML and SageXmlReader classes):
Declare constants for DTD current ans supported older versions
public static final String SAGEXML_CURRENT_VERSION="1.2";
public static final String[] SAGEXML_SUPPORTED_VERSIONS={SAGEXML_CURRENT_VERSION,"1.1"};
public static final String SAGEXML_DTD_PUBLIC_BASE="-//NIELM//DTD SAGESHOWINFO XML ";
public static final String SAGEXML_DTD_PUBLIC=SAGEXML_DTD_PUBLIC_BASE+SAGEXML_CURRENT_VERSION+"//EN";
public static final String SAGEXML_DTD_URI="http://www.sage-community.org/~nielm/nielm_modules/sagexmlinfo/sageshowinfo_1_2.dtd";
// path to local file (using CWD)
public static final String
SAGEXML_DTD_LOCAL="sageshowinfo.dtd";
Define entity resolver class. Returns local DTD if file exists, is readable, and imported XML's Public DTD matches the base ID+one of the supported versions.
class SageXMLResolver implements EntityResolver {
public InputSource resolveEntity (String publicId, String systemId)
{
File file=new File(SageXML.SAGEXML_DTD_LOCAL);
if ( file.canRead() && publicId.startsWith(SageXML.SAGEXML_DTD_PUBLIC_BASE)) {
String version=publicId.substring(SageXML.SAGEXML_DTD_PUBLIC_BASE.length()).replaceAll("//.*$", "");
java.util.List supportedVersList=java.util.Arrays.asList(SageXML.SAGEXML_SUPPORTED_VERSIONS);
if ( supportedVersList.contains(version)) {
// return a special input source
try {
return new InputSource(new FileInputStream(file));
} catch (Exception e){
return null;
}
}
}
return null;//default behaviour
}
}
When parsing, use custom entity resolver
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); DocumentBuilder builder = factory.newDocumentBuilder(); SageXMLResolver resolver=new SageXMLResolver(); builder.setEntityResolver(resolver); SageXMLErrorHander handler=new SageXMLErrorHander(); builder.setErrorHandler(handler); doc=builder.parse((java.io.InputStream)input);