IGN:Update odfpy and make copying in rtf2xml a little nicer

This commit is contained in:
Kovid Goyal 2009-01-30 11:31:19 -08:00
parent d547891422
commit 3ca3d84384
6 changed files with 2024 additions and 1994 deletions

View File

@ -15,7 +15,8 @@
# #
# #
#########################################################################
import sys, os
import sys, os, shutil
class Copy:
"""Copy each changed file to a directory for debugging purposes"""
__dir = ""
@ -64,25 +65,7 @@ class Copy:
of cp. Otherwise, use a safe python method.
"""
write_file = os.path.join(Copy.__dir,new_file)
platform = sys.platform
if platform[:5] == 'linux':
command = 'cp %(file)s %(write_file)s' % vars()
os.system(command)
else:
read_obj = open(file,'r')
write_obj = open(write_file, 'w')
line = "dummy"
while line:
line = read_obj.read(1000)
write_obj.write(line )
read_obj.close()
write_obj.close()
shutil.copyfile(file, write_file)
def rename(self, source, dest):
read_obj = open(source, 'r')
write_obj = open(dest, 'w')
line = 1
while line:
line = read_obj.readline()
write_obj.write(line)
read_obj.close()
write_obj.close()
shutil.copyfile(source, dest)

View File

@ -2060,6 +2060,8 @@ allowed_children = {
),
(TEXTNS,u'chapter') : (
),
(TEXTNS,u'character-count') : (
),
(TEXTNS,u'conditional-text') : (
),
(TEXTNS,u'creation-date') : (
@ -2294,6 +2296,8 @@ allowed_children = {
(TEXTNS,u'illustration-index-entry-template'),
(TEXTNS,u'index-title-template'),
),
(TEXTNS,u'image-count') : (
),
# allowed_children
(TEXTNS,u'index-body') : (
(DR3DNS,u'scene'),
@ -2661,6 +2665,8 @@ allowed_children = {
),
(TEXTNS,u'page') : (
),
(TEXTNS,u'page-count') : (
),
(TEXTNS,u'page-continuation') : (
),
(TEXTNS,u'page-number') : (
@ -2672,6 +2678,8 @@ allowed_children = {
),
(TEXTNS,u'page-variable-set') : (
),
(TEXTNS,u'paragraph-count') : (
),
(TEXTNS,u'placeholder') : (
),
(TEXTNS,u'print-date') : (
@ -2686,6 +2694,8 @@ allowed_children = {
),
(TEXTNS,u'reference-mark-start') : (
),
(TEXTNS,u'reference-ref') : (
),
(TEXTNS,u'ruby') : (
(TEXTNS,u'ruby-base'),
(TEXTNS,u'ruby-text'),
@ -3035,6 +3045,8 @@ allowed_children = {
),
(TEXTNS,u'tab') : (
),
(TEXTNS,u'table-count') : (
),
(TEXTNS,u'table-formula') : (
),
(TEXTNS,u'table-index') : (
@ -3132,6 +3144,8 @@ allowed_children = {
),
(TEXTNS,u'variable-set') : (
),
(TEXTNS,u'word-count') : (
),
}
struct_elements = ( # Unused?
@ -3182,6 +3196,7 @@ allows_text = (
(PRESENTATIONNS,u'footer-decl'),
(PRESENTATIONNS,u'header-decl'),
(SVGNS,u'desc'),
(SVGNS,u'title'),
(TEXTNS,u'a'),
(TEXTNS,u'author-initials'),
(TEXTNS,u'author-name'),
@ -3403,7 +3418,6 @@ required_attributes = {
(DRAWNS,u'glue-point'): (
(SVGNS,u'y'),
(SVGNS,u'x'),
(DRAWNS,u'align'),
(DRAWNS,u'id'),
),
(DRAWNS,u'gradient'): (
@ -4297,35 +4311,47 @@ allowed_attributes = {
(ANIMNS,u'value'),
),
(ANIMNS,u'seq'):(
(PRESENTATIONNS,u'node-type'),
(SMILNS,u'decelerate'),
(SMILNS,u'begin'),
(SMILNS,u'end'),
(PRESENTATIONNS,u'group-id'),
(SMILNS,u'accelerate'),
(SMILNS,u'repeatDur'),
(SMILNS,u'endsync'),
(SMILNS,u'restartDefault'),
(PRESENTATIONNS,u'preset-class'),
(SMILNS,u'fillDefault'),
(PRESENTATIONNS,u'preset-id'),
(SMILNS,u'autoReverse'),
(PRESENTATIONNS,u'preset-sub-type'),
(SMILNS,u'repeatCount'),
(SMILNS,u'dur'),
(SMILNS,u'fill'),
(ANIMNS,u'id'),
(SMILNS,u'restart'),
(PRESENTATIONNS,u'group-id'),
(PRESENTATIONNS,u'master-element'),
(PRESENTATIONNS,u'node-type'),
(PRESENTATIONNS,u'preset-class'),
(PRESENTATIONNS,u'preset-id'),
(PRESENTATIONNS,u'preset-sub-type'),
(SMILNS,u'accelerate'),
(SMILNS,u'autoReverse'),
(SMILNS,u'begin'),
(SMILNS,u'decelerate'),
(SMILNS,u'dur'),
(SMILNS,u'end'),
(SMILNS,u'endsync'),
(SMILNS,u'fill'),
(SMILNS,u'fillDefault'),
(SMILNS,u'repeatCount'),
(SMILNS,u'repeatDur'),
(SMILNS,u'restart'),
(SMILNS,u'restartDefault'),
),
(ANIMNS,u'set'):(
(ANIMNS,u'sub-item'),
(SMILNS,u'accelerate'),
(SMILNS,u'accumulate'),
(SMILNS,u'autoReverse'),
(SMILNS,u'additive'),
(SMILNS,u'attributeName'),
(SMILNS,u'to'),
(ANIMNS,u'sub-item'),
(SMILNS,u'targetElement'),
(SMILNS,u'accumulate'),
(SMILNS,u'begin'),
(SMILNS,u'decelerate'),
(SMILNS,u'dur'),
(SMILNS,u'end'),
(SMILNS,u'fill'),
(SMILNS,u'fillDefault'),
(SMILNS,u'repeatCount'),
(SMILNS,u'repeatDur'),
(SMILNS,u'restart'),
(SMILNS,u'restartDefault'),
(SMILNS,u'targetElement'),
(SMILNS,u'to'),
),
(ANIMNS,u'transitionFilter'):(
(SMILNS,u'direction'),
@ -5789,6 +5815,8 @@ allowed_attributes = {
(MANIFESTNS,'salt'),
(MANIFESTNS,'iteration-count'),
),
(MANIFESTNS,u'manifest'):(
),
# allowed_attributes
(METANS,u'auto-reload'):(
(METANS,u'delay'),
@ -6096,7 +6124,7 @@ allowed_attributes = {
(CHARTNS,u'gap-width'),
(CHARTNS,u'interpolation'),
(CHARTNS,u'interval-major'),
(CHARTNS,u'interval-minor'),
(CHARTNS,u'interval-minor-divisor'),
(CHARTNS,u'japanese-candle-stick'),
(CHARTNS,u'label-arrangement'),
(CHARTNS,u'lines'),
@ -6117,6 +6145,7 @@ allowed_attributes = {
(CHARTNS,u'spline-resolution'),
(CHARTNS,u'stacked'),
(CHARTNS,u'symbol-height'),
(CHARTNS,u'symbol-name'),
(CHARTNS,u'symbol-type'),
(CHARTNS,u'symbol-width'),
(CHARTNS,u'text-overlap'),
@ -6236,11 +6265,9 @@ allowed_attributes = {
),
(STYLENS,u'footer'):(
(STYLENS,u'display'),
(STYLENS,u'dynamic-spacing'),
),
(STYLENS,u'footer-left'):(
(STYLENS,u'display'),
(STYLENS,u'dynamic-spacing'),
),
(STYLENS,u'footer-style'):(
),
@ -6437,7 +6464,6 @@ allowed_attributes = {
),
(STYLENS,u'header'):(
(STYLENS,u'display'),
(STYLENS,u'dynamic-spacing'),
),
(STYLENS,u'header-footer-properties'): (
(FONS,u'background-color'),
@ -6468,7 +6494,6 @@ allowed_attributes = {
),
(STYLENS,u'header-left'):(
(STYLENS,u'display'),
(STYLENS,u'dynamic-spacing'),
),
(STYLENS,u'header-style'):(
),
@ -6480,6 +6505,7 @@ allowed_attributes = {
(STYLENS,u'font-name'),
(STYLENS,u'vertical-pos'),
(STYLENS,u'vertical-rel'),
(SVGNS,u'y'),
(TEXTNS,u'min-label-distance'),
(TEXTNS,u'min-label-width'),
(TEXTNS,u'space-before'),
@ -6534,12 +6560,10 @@ allowed_attributes = {
(STYLENS,u'layout-grid-print'),
(STYLENS,u'layout-grid-ruby-below'),
(STYLENS,u'layout-grid-ruby-height'),
(STYLENS,u'name'),
(STYLENS,u'num-format'),
(STYLENS,u'num-letter-sync'),
(STYLENS,u'num-prefix'),
(STYLENS,u'num-suffix'),
(STYLENS,u'page-usage'),
(STYLENS,u'paper-tray-name'),
(STYLENS,u'print'),
(STYLENS,u'print-orientation'),
@ -7156,7 +7180,6 @@ allowed_attributes = {
(TABLENS,u'cell-range-address'),
),
(TABLENS,u'null-date'):(
(TABLENS,u'date-value-type'),
(TABLENS,u'value-type'),
),
(TABLENS,u'odd-columns'):(

View File

@ -39,15 +39,3 @@ def Algorithm(**args):
def KeyDerivation(**args):
return Element(qname = (MANIFESTNS,'key-derivation'), **args)
if __name__ == "__main__":
import cStringIO
xml=cStringIO.StringIO()
m = Manifest()
f = FileEntry(mediatype="text/xml", fullpath="content.xml")
m.addElement(f)
m.toXml(0,xml)
print xml.getvalue()

View File

@ -17,7 +17,7 @@
#
# Contributor(s):
#
TOOLSVERSION = u"ODFPY/0.8.1dev"
TOOLSVERSION = u"ODFPY/0.8.2dev"
ANIMNS = u"urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
DBNS = u"urn:oasis:names:tc:opendocument:xmlns:database:1.0"
@ -49,7 +49,7 @@ TABLENS = u"urn:oasis:names:tc:opendocument:xmlns:table:1.0"
TEXTNS = u"urn:oasis:names:tc:opendocument:xmlns:text:1.0"
XFORMSNS = u"http://www.w3.org/2002/xforms"
XLINKNS = u"http://www.w3.org/1999/xlink"
XMLNS = "http://www.w3.org/XML/1998/namespace"
XMLNS = u"http://www.w3.org/XML/1998/namespace"
nsdict = {

View File

@ -64,6 +64,12 @@ odmimetypes = {
'application/vnd.oasis.opendocument.text-web': '.oth',
}
class OpaqueObject:
def __init__(self, filename, mediatype, content=None):
self.mediatype = mediatype
self.filename = filename
self.content = content
class OpenDocument:
""" A class to hold the content of an OpenDocument document
Use the xml method to write the XML
@ -76,6 +82,7 @@ class OpenDocument:
def __init__(self, mimetype, add_generator=True):
self.mimetype = mimetype
self.childobjects = []
self._extra = []
self.folder = "" # Always empty for toplevel documents
self.topnode = Document(mimetype=self.mimetype)
self.topnode.ownerDocument = self
@ -303,12 +310,15 @@ class OpenDocument:
else:
self.thumbnail = filecontent
def addObject(self, document):
def addObject(self, document, objectname=None):
""" Add an object. The object must be an OpenDocument class
The return value will be the folder in the zipfile the object is stored in
"""
self.childobjects.append(document)
if objectname is None:
document.folder = "%s/Object %d" % (self.folder, len(self.childobjects))
else:
document.folder = objectname
return ".%s" % document.folder
def _savePictures(self, object, folder):
@ -382,6 +392,14 @@ class OpenDocument:
zi.external_attr = UNIXPERMS
self._z.writestr(zi, self.thumbnail)
# Write any extra files
for op in self._extra:
self.manifest.addElement(manifest.FileEntry(fullpath=op.filename, mediatype=op.mediatype))
zi = zipfile.ZipInfo(op.filename.encode('utf-8'), self._now)
zi.compress_type = zipfile.ZIP_DEFLATED
zi.external_attr = UNIXPERMS
if op.content is not None:
self._z.writestr(zi, op.content)
# Write manifest
zi = zipfile.ZipInfo("META-INF/manifest.xml", self._now)
zi.compress_type = zipfile.ZIP_DEFLATED
@ -528,15 +546,20 @@ def load(odffile):
parser.parse(inpsrc)
del doc._parsing
except KeyError, v: pass
# Add the thumbnail here
# Add the images here
# FIXME: Add subobjects correctly here
for mentry,mvalue in manifest.items():
if mentry[:9] == "Pictures/" and len(mentry) > 9:
doc.addPicture(mvalue['full-path'], mvalue['media-type'], z.read(mentry))
elif mentry == "Thumbnails/thumbnail.png":
doc.addThumbnail(z.read(mentry))
elif mentry in ('settings.xml', 'meta.xml', 'content.xml', 'styles.xml'):
pass
else:
pass # Add the SUN junk here to the struct somewhere
if mvalue['full-path'][-1] == '/':
doc._extra.append(OpaqueObject(mvalue['full-path'], mvalue['media-type'], None))
else:
doc._extra.append(OpaqueObject(mvalue['full-path'], mvalue['media-type'], z.read(mentry)))
# Add the SUN junk here to the struct somewhere
# It is cached data, so it can be out-of-date
z.close()
b = doc.getElementsByType(Body)

View File

@ -231,6 +231,19 @@ class ODFContentParser(xml.sax.saxutils.XMLGenerator):
self._callback_func = callback_func
xml.sax.saxutils.XMLGenerator.__init__(self, out, encoding)
def _qname(self, name):
"""Builds a qualified name from a (ns_url, localname) pair"""
if name[0]:
if name[0] == u'http://www.w3.org/XML/1998/namespace':
return u'xml' + ":" + name[1]
# The name is in a non-empty namespace
prefix = self._current_context[name[0]]
if prefix:
# If it is not the default namespace, prepend the prefix
return prefix + ":" + name[1]
# Return the unqualified name
return name[1]
def startElementNS(self, name, qname, attrs):
if name == (TEXTNS, u'user-field-decl'):
field_name = attrs.get((TEXTNS, u'name'))