Package translate :: Package storage :: Package placeables :: Module lisa |
[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.placeables.lisa

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2008-2009 Zuza Software Foundation
      5  #
      6  # This file is part of the Translate Toolkit.
      7  #
      8  # This program is free software; you can redistribute it and/or modify
      9  # it under the terms of the GNU General Public License as published by
     10  # the Free Software Foundation; either version 2 of the License, or
     11  # (at your option) any later version.
     12  #
     13  # This program is distributed in the hope that it will be useful,
     14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  # GNU General Public License for more details.
     17  #
     18  # You should have received a copy of the GNU General Public License
     19  # along with this program; if not, see <http://www.gnu.org/licenses/>.
     20
     21  from lxml import etree
     22
     23  from translate.misc.xml_helpers import normalize_xml_space
     24  from translate.storage.placeables import base, xliff, StringElem
     25  from translate.storage.xml_extract import misc
     26
     27  __all__ = ['xml_to_strelem', 'strelem_to_xml']
     28  # Use the above functions as entry points into this module. The rest are used by these functions.
     29
     30
     31 -def make_empty_replacement_placeable(klass, node, xml_space="preserve"):
     32      try:
     33          return klass(
     34              id=node.attrib[u'id'],
     35              rid=node.attrib.get('rid', None),
     36              xid=node.attrib.get('xid', None),
     37              xml_attrib=node.attrib,
     38          )
     39      except KeyError:
     40          pass
     41      return klass()
     42
     43
     44 -def make_g_placeable(klass, node, xml_space="default"):
     45      return klass(
     46          id=node.attrib[u'id'],
     47          sub=xml_to_strelem(node, xml_space).sub,
     48          xml_attrib=node.attrib,
     49      )
     50
     51
     52 -def not_yet_implemented(klass, node, xml_space="preserve"):
     53      raise NotImplementedError
     54
     55
     56 -def make_unknown(klass, node, xml_space="preserve"):
     57      assert klass is xliff.UnknownXML
     58
     59      sub = xml_to_strelem(node, xml_space).sub
     60      id = node.get('id', None)
     61      rid = node.get('rid', None)
     62      xid = node.get('xid', None)
     63
     64      return klass(sub=sub, id=id, rid=rid, xid=xid, xml_node=node)
     65
     66  _class_dictionary = {
     67      #u'bpt': (xliff.Bpt, not_yet_implemented),
     68      u'bx': (xliff.Bx, make_empty_replacement_placeable),
     69      #u'ept': (xliff.Ept, not_yet_implemented),
     70      u'ex': (xliff.Ex, make_empty_replacement_placeable),
     71      u'g': (xliff.G, make_g_placeable),
     72      #u'it': (xliff.It, not_yet_implemented),
     73      #u'ph': (xliff.Ph, not_yet_implemented),
     74      #u'sub': (xliff.Sub, not_yet_implemented),
     75      u'x': (xliff.X, make_empty_replacement_placeable),
     76  }
     77
     78
     79 -def make_placeable(node, xml_space):
     80      _namespace, tag = misc.parse_tag(node.tag)
     81      if tag in _class_dictionary:
     82          klass, maker = _class_dictionary[tag]
     83      else:
     84          klass, maker = xliff.UnknownXML, make_unknown
     85      return maker(klass, node, xml_space)
     86
     87
     88 -def as_unicode(string):
     89      if isinstance(string, unicode):
     90          return string
     91      elif isinstance(string, StringElem):
     92          return unicode(string)
     93      else:
     94          return unicode(string.decode('utf-8'))
     95
     96
     97 -def xml_to_strelem(dom_node, xml_space="preserve"):
     98      if dom_node is None:
     99          return StringElem()
    100      if isinstance(dom_node, basestring):
    101          dom_node = etree.fromstring(dom_node)
    102      normalize_xml_space(dom_node, xml_space, remove_start=True)
    103      result = StringElem()
    104      sub = result.sub # just an optimisation
    105      for child_dom_node in dom_node:
    106          sub.append(make_placeable(child_dom_node, xml_space))
    107          if child_dom_node.tail:
    108              sub.append(StringElem(unicode(child_dom_node.tail)))
    109
    110      # This is just a strange way of inserting the first text and avoiding a
    111      # call to .prune() which is very expensive. We assume the tree is optimal.
    112      node_text = dom_node.text
    113      if sub and node_text:
    114          sub.insert(0, StringElem(unicode(node_text)))
    115      elif node_text:
    116          sub.append(unicode(node_text))
    117      return result
    118
    119  # ==========================================================
    120
    121
    122 -def placeable_as_dom_node(placeable, tagname):
    123      dom_node = etree.Element(tagname)
    124      if placeable.id is not None:
    125          dom_node.attrib['id'] = placeable.id
    126      if placeable.xid is not None:
    127          dom_node.attrib['xid'] = placeable.xid
    128      if placeable.rid is not None:
    129          dom_node.attrib['rid'] = placeable.rid
    130
    131      if hasattr(placeable, 'xml_attrib'):
    132          for attrib, value in placeable.xml_attrib.items():
    133              dom_node.set(attrib, value)
    134
    135      return dom_node
    136
    137
    138 -def unknown_placeable_as_dom_node(placeable):
    139      assert type(placeable) is xliff.UnknownXML
    140
    141      from copy import copy
    142      node = copy(placeable.xml_node)
    143      for i in range(len(node)):
    144          del node[0]
    145      node.tail = None
    146      node.text = None
    147
    148      return node
    149
    150  _placeable_dictionary = {
    151      xliff.Bpt: lambda placeable: placeable_as_dom_node(placeable, 'bpt'),
    152      xliff.Bx: lambda placeable: placeable_as_dom_node(placeable, 'bx'),
    153      xliff.Ept: lambda placeable: placeable_as_dom_node(placeable, 'ept'),
    154      xliff.Ex: lambda placeable: placeable_as_dom_node(placeable, 'ex'),
    155      xliff.G: lambda placeable: placeable_as_dom_node(placeable, 'g'),
    156      xliff.It: lambda placeable: placeable_as_dom_node(placeable, 'it'),
    157      xliff.Ph: lambda placeable: placeable_as_dom_node(placeable, 'ph'),
    158      xliff.Sub: lambda placeable: placeable_as_dom_node(placeable, 'sub'),
    159      xliff.X: lambda placeable: placeable_as_dom_node(placeable, 'x'),
    160      xliff.UnknownXML: unknown_placeable_as_dom_node,
    161      base.Bpt: lambda placeable: placeable_as_dom_node(placeable, 'bpt'),
    162      base.Bx: lambda placeable: placeable_as_dom_node(placeable, 'bx'),
    163      base.Ept: lambda placeable: placeable_as_dom_node(placeable, 'ept'),
    164      base.Ex: lambda placeable: placeable_as_dom_node(placeable, 'ex'),
    165      base.G: lambda placeable: placeable_as_dom_node(placeable, 'g'),
    166      base.It: lambda placeable: placeable_as_dom_node(placeable, 'it'),
    167      base.Ph: lambda placeable: placeable_as_dom_node(placeable, 'ph'),
    168      base.Sub: lambda placeable: placeable_as_dom_node(placeable, 'sub'),
    169      base.X: lambda placeable: placeable_as_dom_node(placeable, 'x'),
    170  }
    171
    172
    173 -def xml_append_string(node, string):
    174      if not len(node):
    175          if not node.text:
    176              node.text = unicode(string)
    177          else:
    178              node.text += unicode(string)
    179      else:
    180          lastchild = node.getchildren()[-1]
    181          if lastchild.tail is None:
    182              lastchild.tail = ''
    183          lastchild.tail += unicode(string)
    184      return node
    185
    186
    187 -def strelem_to_xml(parent_node, elem):
    188      if isinstance(elem, unicode):
    189          return xml_append_string(parent_node, elem)
    190      if not isinstance(elem, StringElem):
    191          return parent_node
    192
    193      if type(elem) is StringElem and elem.isleaf():
    194          return xml_append_string(parent_node, elem)
    195
    196      if elem.__class__ in _placeable_dictionary:
    197          node = _placeable_dictionary[elem.__class__](elem)
    198          parent_node.append(node)
    199      else:
    200          node = parent_node
    201
    202      for sub in elem.sub:
    203          strelem_to_xml(node, sub)
    204
    205      return parent_node
    206
    207
    208 -def parse_xliff(pstr):
    209      try:
    210          return xml_to_strelem(etree.fromstring('<source>%s</source>' % (pstr)))
    211      except Exception, exc:
    212          raise
    213          return None
    214  xliff.parsers = [parse_xliff]
    215