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);