summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorR.D. Vaughan <r.d.vaughan@rogers.com>2011-07-09 21:03:30 (GMT)
committer Raymond Wagner <rwagner@mythtv.org>2011-07-10 19:36:18 (GMT)
commit8f8d6620bb3a6d22913521bde86d7677db731b4e (patch)
treed08d6b7b6ecc83198474e4af59b00ecbe11aba24
parent6dfda22ae71fe98219f6f70f539a85a9249360dd (diff)
ttvdb grabber performance improvements
Change Log: 1) Removed complex element tree searches from the XSLT stylesheet and substituted XPATH lxml functions 2) Minor docmentation corrections Refs #9859
-rw-r--r--mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl23
-rw-r--r--mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py50
2 files changed, 60 insertions, 13 deletions
diff --git a/mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl b/mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl
index be6b91e..834e2b6 100644
--- a/mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl
+++ b/mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl
@@ -2,14 +2,15 @@
<!--
thetvdb.com Video data conversion to MythTV Universal Metadata Format
See: http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format
--->
+-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
- xmlns:tvdbXpath="http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format">
+ xmlns:tvdbXpath="http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format"
+ >
<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
-
+
<!--
This template calls all other templates which allows for multiple sources to be processed
within a single Xslt file
@@ -21,17 +22,17 @@
</metadata>
</xsl:if>
</xsl:template>
-
- <xsl:template name="tvdbVideoData">
+
+ <xsl:template name="tvdbVideoData">
<xsl:for-each select="//Data/Series">
<item>
<title><xsl:value-of select="normalize-space(SeriesName)"/></title>
- <xsl:if test="//Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]/EpisodeName/text() != ''">
- <subtitle><xsl:value-of select="normalize-space(//Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]/EpisodeName)"/></subtitle>
+ <xsl:if test="tvdbXpath:getValue(//requestDetails, //Data, 'subtitle') != ''">
+ <subtitle><xsl:value-of select="normalize-space(tvdbXpath:getResult())"/></subtitle>
</xsl:if>
<language><xsl:value-of select="normalize-space(Language)"/></language>
- <xsl:if test="//Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]/Overview/text() != ''">
- <description><xsl:value-of select="normalize-space(tvdbXpath:htmlToString(string(//Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]/Overview)))"/></description>
+ <xsl:if test="tvdbXpath:getValue(//requestDetails, //Data, 'description') != ''">
+ <description><xsl:value-of select="normalize-space(tvdbXpath:htmlToString(tvdbXpath:getResult()))"/></description>
</xsl:if>
<season><xsl:value-of select="normalize-space(//requestDetails/@season)"/></season>
<episode><xsl:value-of select="normalize-space(//requestDetails/@episode)"/></episode>
@@ -68,13 +69,13 @@
<runtime><xsl:value-of select="normalize-space(Runtime)"/></runtime>
</xsl:if>
<inetref><xsl:value-of select="normalize-space(id)"/></inetref>
- <xsl:if test="./IMDB_ID/text() != '' and //Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]/IMDB_ID/text() = ''">
+ <xsl:if test="./IMDB_ID/text() != '' and tvdbXpath:getValue(//requestDetails, //Data, 'IMDB') = ''">
<imdb><xsl:value-of select="normalize-space(substring-after(string(IMDB_ID), 'tt'))"/></imdb>
</xsl:if>
<xsl:if test="./zap2it_id/text() != ''">
<tmsref><xsl:value-of select="normalize-space(zap2it_id)"/></tmsref>
</xsl:if>
- <xsl:for-each select="//Data/Episode[SeasonNumber/text()=//requestDetails/@season and EpisodeNumber/text()=//requestDetails/@episode]">
+ <xsl:for-each select="tvdbXpath:getValue(//requestDetails, //Data, 'allEpisodes', 'allresults')">
<xsl:if test="./IMDB_ID/text() != ''">
<imdb><xsl:value-of select="normalize-space(substring-after(string(IMDB_ID), 'tt'))"/></imdb>
</xsl:if>
diff --git a/mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py b/mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py
index c2c3b0c..ff5dc68 100644
--- a/mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py
+++ b/mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py
@@ -12,7 +12,7 @@
# License:Creative Commons GNU GPL v2
# (http://creativecommons.org/licenses/GPL/2.0/)
#-------------------------------------
-__title__ ="tvdbXslt - XPath and XSLT functions for the Tribute.ca grabber"
+__title__ ="tvdbXslt - XPath and XSLT functions for the ttvdb.com grabber"
__author__="R.D. Vaughan"
__purpose__='''
This python script is intended to perform a variety of utility functions
@@ -21,9 +21,10 @@ See this link for the specifications:
http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format
'''
-__version__="v0.1.1"
+__version__="v0.1.2"
# 0.1.0 Initial development
# 0.1.1 Converted categories, genre, ... etc text characters to be XML compliant
+# 0.1.2 Performance improvements by removing complex data searches from the XLST stylesheet
# Specify the class names that have XPath extention functions
@@ -97,6 +98,13 @@ class xpathFunctions(object):
'poster': [u'//Banner[BannerType/text()="season" and Language/text()="%(language)s" and Season/text()="%(season)s" and BannerType2/text()="season"]', u'//Banner[BannerType/text()="%(type)s" and Language/text()="%(language)s"]', u'//Banner[BannerType/text()="season" and Language/text()="en" and Season/text()="%(season)s" and BannerType2/text()="season"]', u'//Banner[BannerType/text()="season" and Season/text()="%(season)s" and BannerType2/text()="season"]', u'//Banner[BannerType/text()="%(type)s" and Language/text()="en"]', u'//Banner[BannerType/text()="%(type)s"]'],
'banner': ['//Banner[BannerType/text()="season" and Language/text()="%(language)s" and Season/text()="%(season)s" and BannerType2/text()="seasonwide"]', u'//Banner[BannerType/text()="series" and Language/text()="%(language)s" and BannerType2/text()="graphical"]', '//Banner[BannerType/text()="season" and Language/text()="en" and Season/text()="%(season)s" and BannerType2/text()="seasonwide"]', '//Banner[BannerType/text()="season" and Season/text()="%(season)s" and BannerType2/text()="seasonwide"]', u'//Banner[BannerType/text()="series" and Language/text()="en" and BannerType2/text()="graphical"]', '//Banner[BannerType/text()="series" and BannerType2/text()="graphical"]'],
}
+ self.dataFilters = {
+ 'subtitle': u'//Data/Episode[SeasonNumber/text()="%(season)s" and EpisodeNumber/text()="%(episode)s"]/EpisodeName/text()',
+ 'description': u'//Data/Episode[SeasonNumber/text()="%(season)s" and EpisodeNumber/text()="%(episode)s"]/Overview/text()',
+ 'IMDB': u'//Data/Episode[SeasonNumber/text()="%(season)s" and EpisodeNumber/text()="%(episode)s"]/IMDB_ID/text()',
+ 'allEpisodes': u'//Data/Episode[SeasonNumber/text()="%(season)s" and EpisodeNumber/text()="%(episode)s"]',
+ }
+ self.persistentResult = ''
# end __init__()
######################################################################################################
@@ -114,6 +122,8 @@ class xpathFunctions(object):
'htmlToString': self.htmlToString,
'stringToList': self.stringToList,
'imageElements': self.imageElements,
+ 'getValue': self.getValue,
+ 'getResult': self.getResult,
}
return
# end buildFuncDict()
@@ -254,6 +264,42 @@ class xpathFunctions(object):
return self.ampReplace(re.sub(u"(?s)<[^>]*>|&#?\w+;", fixup, self.textUtf8(text))).replace(u'\n',u' ')
# end massageText()
+ def getValue(self, context, *args):
+ ''' Use xpath filters to perform complex element tree data searching. This is significantly more
+ efficent than using the same search statements in a xslt template. Also save the results so that the
+ data can be used both in an if statement then actually use the data without performing an identical
+ element tree data search.
+ return the results of the data search
+ '''
+ if len(args) < 4:
+ allValues = False
+ else:
+ allValues = True
+ parmDict = {
+ 'season': args[0][0].attrib['season'],
+ 'episode': args[0][0].attrib['episode'],
+ }
+ xpathFilter = etree.XPath(self.dataFilters[args[2]] % parmDict)
+ results = xpathFilter(args[1][0])
+
+ # Sometimes all the results are required
+ if allValues == True:
+ self.persistentResult = results
+ return self.persistentResult
+
+ if len(results):
+ self.persistentResult = results[0] # Return only the first result
+ else:
+ self.persistentResult = ''
+ return self.persistentResult
+ # end getValue()
+
+ def getResult(self, context):
+ ''' Return the last saved result
+ '''
+ return self.persistentResult
+ # end getResult()
+
######################################################################################################
#
# End of XPath extension functions