diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 65be3f5e4..290d83d38 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -42,8 +42,10 @@ import logging import re from lxml import etree, objectify + +from openlp.core.lib import translate from openlp.plugins.songs.lib import VerseType -from openlp.plugins.songs.lib.db import Author, Song +from openlp.plugins.songs.lib.db import Author, Song, Topic log = logging.getLogger(__name__) @@ -246,7 +248,7 @@ class OpenLyricsParser(object): This class represents the converter for Song to/from `OpenLyrics `_ XML. """ - # TODO: complete OpenLyrics standard implementation! + # TODO: complete OpenLyrics standard implementation as fare as possible! def __init__(self, manager): self.manager = manager @@ -288,7 +290,7 @@ class OpenLyricsParser(object): """ Create and save a Song from OpenLyrics format xml. """ - # No xml get out of here + # No xml get out of here. if not xml: return 0 song = Song() @@ -296,19 +298,18 @@ class OpenLyricsParser(object): xml = xml[38:] song_xml = objectify.fromstring(xml) properties = song_xml.properties - song.copyright = unicode(properties.copyright.text) - if song.copyright == u'None': + # Process Copyright + try: + song.copyright = unicode(properties.copyright.text) + if song.copyright == u'None': + song.copyright = u'' + except AttributeError: song.copyright = u'' - song.topics = [] - song.book = None + # Process CCLI number try: song.ccli_number = unicode(properties.ccliNo.text) except AttributeError: song.ccli_number = u'' - try: - song.theme_name = unicode(properties.themes.theme) - except AttributeError: - song.theme_name = u'' # Process Titles for title in properties.titles.title: if not song.title: @@ -325,26 +326,29 @@ class OpenLyricsParser(object): search_text = u'' song.verse_order = u'' for lyrics in song_xml.lyrics: - for verse in song_xml.lyrics.verse: + for verse in lyrics.verse: text = u'' - for line in verse.lines.line: - line = unicode(line) - if not text: - text = line - else: - text += u'\n' + line - type = VerseType.expand_string(verse.attrib[u'name'][0]) - # Here we need to create the verse order for the case that the - # song does not have a verseOrder property. - sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) + # Note that the element will not be in OpenLyrics 0.8: + # http://code.google.com/p/openlyrics/issues/detail?id=8 + for line in verse.lines: + for line in line.line: + line = unicode(line) + if not text: + text = line + else: + text += u'\n' + line + type_ = VerseType.expand_string(verse.attrib[u'name'][0]) + # TODO: Here we need to create the verse order for the case that + # the song does not have a verseOrder property. + sxml.add_verse_to_lyrics(type_, verse.attrib[u'name'][1], text) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + # Process verse order try: song.verse_order = unicode(properties.verseOrder.text) except AttributeError: # TODO: Do not allow empty verse order. - # Do not worry! pass if song.verse_order == u'None': song.verse_order = u'' @@ -358,16 +362,26 @@ class OpenLyricsParser(object): song.comments += u'\n' + comment except AttributeError: pass - song.song_number = u'' # Process Authors try: for author in properties.authors.author: self._process_author(author.text, song) except AttributeError: - # No Author in XML so ignore pass + if not song.authors: + # Add "Author unknown" (can be translated) + self._process_author(translate('SongsPlugin.XML', + 'Author unknown'), song) + # Process Topcis + try: + for topic in properties.themes.theme: + self._process_topic(topic.text, song) + except AttributeError: + pass + # Properties not yet supported. + song.book = None + song.song_number = u'' self.manager.save_object(song) - # TODO: better return song itself, instead of song.id return song.id def _add_text_to_element(self, tag, parent, text=None, label=None): @@ -396,17 +410,43 @@ class OpenLyricsParser(object): def _process_author(self, name, song): """ - Find or create an Author from display_name. + Finds an existing Author or creates a new Author and adds it to the song + object. + + ``name`` + The display_name of the song (string). + + ``song`` + The song the Author will be added to. """ + if not name: + return name = unicode(name) author = self.manager.get_object_filtered(Author, Author.display_name == name) - if author: - # should only be one! so take the first - song.authors.append(author) - else: - # Need a new author - new_author = Author.populate(first_name=name.rsplit(u' ', 1)[0], - last_name=name.rsplit(u' ', 1)[1], display_name=name) - self.manager.save_object(new_author) - song.authors.append(new_author) + if author is None: + # We need to create a new author, as the author does not exist. + author = Author.populate(first_name=name.rsplit(u' ', 1)[0], + last_name=name.rsplit(u' ', 1)[1], display_name=name) + self.manager.save_object(author) + song.authors.append(author) + + def _process_topic(self, topictext, song): + """ + Finds an existing Topic or creates a new Topic and adds it to the song + object. + + ``topictext`` + The topictext we add to the song (string). + + ``song`` + The song the Topic will be added to. + """ + topictext = unicode(topictext) + # Check if topic already exists in the database. + topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) + if topic is None: + # We need to create a new topic, as the topic does not exist. + topic = Topic.populate(name=topictext) + self.manager.save_object(topic) + song.topics.append(topic)