Rework xml unicode handling

This commit is contained in:
Matt 2020-03-06 23:38:43 -05:00
parent 183c05919e
commit bb0a539074
4 changed files with 57 additions and 68 deletions

View File

@ -13,8 +13,6 @@ from .utils import event
from .utils import validate from .utils import validate
from .utils import values from .utils import values
from .utils import JSONRPC from .utils import JSONRPC
from .utils import indent
from .utils import write_xml
from .utils import compare_version from .utils import compare_version
from .utils import unzip from .utils import unzip
from .utils import create_id from .utils import create_id

View File

@ -266,44 +266,6 @@ def values(item, keys):
return (item[key.replace('{', "").replace('}', "")] if isinstance(key, text_type) and key.startswith('{') else key for key in keys) return (item[key.replace('{', "").replace('}', "")] if isinstance(key, text_type) and key.startswith('{') else key for key in keys)
def indent(elem, level=0):
''' Prettify xml docs.
'''
try:
i = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level + 1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
except Exception as error:
LOG.exception(error)
return
def write_xml(content, file):
if isinstance(content, text_type):
content = content.encode('utf-8')
with open(file, 'wb') as infile:
# replace apostrophes with double quotes only in xml keys, not texts
def replace_apostrophes(match):
return match.group(0).replace(b"'", b'"')
content = re.sub(b"<(.*?)>", replace_apostrophes, content)
content = content.replace(b'?>', b' standalone="yes" ?>', 1)
infile.write(content)
def delete_folder(path): def delete_folder(path):
''' Delete objects from kodi cache ''' Delete objects from kodi cache

View File

@ -5,11 +5,11 @@ from __future__ import division, absolute_import, print_function, unicode_litera
import logging import logging
import os import os
import xml.etree.ElementTree as etree from lxml import etree
from kodi_six import xbmc from kodi_six import xbmc
from . import translate, indent, write_xml, dialog, settings from . import translate, dialog, settings
################################################################################################# #################################################################################################
@ -75,8 +75,8 @@ def sources():
except Exception as error: except Exception as error:
LOG.exception(error) LOG.exception(error)
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def tvtunes_nfo(path, urls): def tvtunes_nfo(path, urls):
@ -95,8 +95,8 @@ def tvtunes_nfo(path, urls):
for url in urls: for url in urls:
etree.SubElement(xml, 'file').text = url etree.SubElement(xml, 'file').text = url
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), path) tree.write(path, pretty_print=True)
def advanced_settings(): def advanced_settings():
@ -125,8 +125,8 @@ def advanced_settings():
LOG.warning("cleanonupdate disabled") LOG.warning("cleanonupdate disabled")
video.remove(cleanonupdate) video.remove(cleanonupdate)
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), path) tree.write(path, pretty_print=True)
dialog("ok", heading="{jellyfin}", line1=translate(33097)) dialog("ok", heading="{jellyfin}", line1=translate(33097))
xbmc.executebuiltin('RestartApp') xbmc.executebuiltin('RestartApp')

View File

@ -6,13 +6,13 @@ from __future__ import division, absolute_import, print_function, unicode_litera
import logging import logging
import os import os
import shutil import shutil
import xml.etree.ElementTree as etree from lxml import etree
from six.moves.urllib.parse import urlencode from six.moves.urllib.parse import urlencode
from kodi_six import xbmc, xbmcvfs from kodi_six import xbmc, xbmcvfs
from database import Database, jellyfin_db, get_sync, save_sync from database import Database, jellyfin_db, get_sync, save_sync
from helper import translate, api, indent, write_xml, window, event from helper import translate, api, window, event
from jellyfin import Jellyfin from jellyfin import Jellyfin
################################################################################################# #################################################################################################
@ -126,8 +126,8 @@ def verify_kodi_defaults():
xml = etree.parse(file).getroot() xml = etree.parse(file).getroot()
xml.set('order', str(17 + index)) xml.set('order', str(17 + index))
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
playlist_path = xbmc.translatePath("special://profile/playlists/video") playlist_path = xbmc.translatePath("special://profile/playlists/video")
@ -272,7 +272,12 @@ class Views(object):
file = os.path.join(path, "jellyfin%s%s.xsp" % (view['Media'], view['Id'])) file = os.path.join(path, "jellyfin%s%s.xsp" % (view['Media'], view['Id']))
try: try:
xml = etree.parse(file).getroot() if os.path.isfile(file):
xml = etree.parse(file).getroot()
else:
xml = etree.Element('smartplaylist', {'type': view['Media']})
etree.SubElement(xml, 'name')
etree.SubElement(xml, 'match')
except Exception: except Exception:
LOG.warning("Unable to parse file '%s'", file) LOG.warning("Unable to parse file '%s'", file)
xml = etree.Element('smartplaylist', {'type': view['Media']}) xml = etree.Element('smartplaylist', {'type': view['Media']})
@ -292,8 +297,8 @@ class Views(object):
rule = etree.SubElement(xml, 'rule', {'field': "tag", 'operator': "is"}) rule = etree.SubElement(xml, 'rule', {'field': "tag", 'operator': "is"})
etree.SubElement(rule, 'value').text = view['Tag'] etree.SubElement(rule, 'value').text = view['Tag']
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def add_nodes(self, path, view, mixed=False): def add_nodes(self, path, view, mixed=False):
@ -316,7 +321,13 @@ class Views(object):
file = os.path.join(path, "jellyfin_%s.xml" % view['Tag'].replace(" ", "")) file = os.path.join(path, "jellyfin_%s.xml" % view['Tag'].replace(" ", ""))
try: try:
xml = etree.parse(file).getroot() if os.path.isfile(file):
xml = etree.parse(file).getroot()
else:
xml = self.node_root('folder' if item_type == 'favorites' and view['Media'] == 'episodes' else 'filter', index)
etree.SubElement(xml, 'label')
etree.SubElement(xml, 'match')
etree.SubElement(xml, 'content')
except Exception: except Exception:
LOG.warning("Unable to parse file '%s'", file) LOG.warning("Unable to parse file '%s'", file)
xml = self.node_root('folder' if item_type == 'favorites' and view['Media'] == 'episodes' else 'filter', index) xml = self.node_root('folder' if item_type == 'favorites' and view['Media'] == 'episodes' else 'filter', index)
@ -348,8 +359,8 @@ class Views(object):
else: else:
self.node_all(xml) self.node_all(xml)
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def node_root(self, root, index): def node_root(self, root, index):
@ -372,8 +383,14 @@ class Views(object):
index = self.sync['SortedViews'].index(view['Id']) index = self.sync['SortedViews'].index(view['Id'])
try: try:
xml = etree.parse(file).getroot() if os.path.isfile(file):
xml.set('order', str(index)) xml = etree.parse(file).getroot()
xml.set('order', str(index))
else:
xml = self.node_root('filter', index)
etree.SubElement(xml, 'label')
etree.SubElement(xml, 'match')
etree.SubElement(xml, 'content')
except Exception as error: except Exception as error:
LOG.exception(error) LOG.exception(error)
xml = self.node_root('main', index) xml = self.node_root('main', index)
@ -382,8 +399,8 @@ class Views(object):
label = xml.find('label') label = xml.find('label')
label.text = view['Name'] if not mixed else "%s (%s)" % (view['Name'], translate(view['Media'])) label.text = view['Name'] if not mixed else "%s (%s)" % (view['Name'], translate(view['Media']))
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def node(self, folder, view): def node(self, folder, view):
@ -412,7 +429,14 @@ class Views(object):
def add_node(self, index, file, view, node, name): def add_node(self, index, file, view, node, name):
try: try:
xml = etree.parse(file).getroot() if os.path.isfile(file):
xml = etree.parse(file).getroot()
else:
xml = self.node_root('filter', index)
etree.SubElement(xml, 'label')
etree.SubElement(xml, 'match')
etree.SubElement(xml, 'content')
except Exception: except Exception:
LOG.warning("Unable to parse file '%s'", file) LOG.warning("Unable to parse file '%s'", file)
xml = self.node_root('filter', index) xml = self.node_root('filter', index)
@ -437,13 +461,18 @@ class Views(object):
etree.SubElement(rule, 'value').text = view['Tag'] etree.SubElement(rule, 'value').text = view['Tag']
getattr(self, 'node_' + node)(xml) # get node function based on node type getattr(self, 'node_' + node)(xml) # get node function based on node type
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def add_dynamic_node(self, index, file, view, node, name, path): def add_dynamic_node(self, index, file, view, node, name, path):
try: try:
xml = etree.parse(file).getroot() if os.path.isfile(file):
xml = etree.parse(file).getroot()
else:
xml = self.node_root('filter', index)
etree.SubElement(xml, 'label')
etree.SubElement(xml, 'content')
except Exception: except Exception:
LOG.warning("Unable to parse file '%s'", file) LOG.warning("Unable to parse file '%s'", file)
xml = self.node_root('folder', index) xml = self.node_root('folder', index)
@ -454,8 +483,8 @@ class Views(object):
label.text = name label.text = name
getattr(self, 'node_' + node)(xml, path) getattr(self, 'node_' + node)(xml, path)
indent(xml) tree = etree.ElementTree(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file) tree.write(file, pretty_print=True)
def node_all(self, root): def node_all(self, root):