Skip to content

Commit

Permalink
ttvdb grabber performance improvements
Browse files Browse the repository at this point in the history
Change Log:
1) Removed complex element tree searches from the XSLT stylesheet and
substituted XPATH lxml functions
2) Minor documentation corrections

Fixes #9859
  • Loading branch information
rdv authored and wagnerrp committed Jul 10, 2011
1 parent 412b2bf commit 774f0d3
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
15 changes: 8 additions & 7 deletions mythtv/bindings/python/MythTV/ttvdb/XSLT/tvdbVideo.xsl 100644 → 100755
Expand Up @@ -6,7 +6,8 @@
<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"/>

Expand All @@ -26,12 +27,12 @@
<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>
Expand Down Expand Up @@ -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>
Expand Down
50 changes: 48 additions & 2 deletions mythtv/bindings/python/MythTV/ttvdb/tvdbXslt.py 100644 → 100755
Expand Up @@ -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
Expand All @@ -21,9 +21,10 @@
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
Expand Down Expand Up @@ -97,6 +98,13 @@ def __init__(self):
'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__()

######################################################################################################
Expand All @@ -114,6 +122,8 @@ def buildFuncDict(self):
'htmlToString': self.htmlToString,
'stringToList': self.stringToList,
'imageElements': self.imageElements,
'getValue': self.getValue,
'getResult': self.getResult,
}
return
# end buildFuncDict()
Expand Down Expand Up @@ -254,6 +264,42 @@ def fixup(m):
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
Expand Down

0 comments on commit 774f0d3

Please sign in to comment.