From 4c7c6bd399dfb50038a7c44fc6b3811ba82759e5 Mon Sep 17 00:00:00 2001 From: Nicolas Pettiaux Date: Sun, 5 Jun 2022 11:23:43 +0200 Subject: [PATCH] ajout des sources originales --- OOoPy-1.11/PKG-INFO | 336 +++++++ OOoPy-1.11/README.html | 593 ++++++++++++ OOoPy-1.11/README.rst | 320 ++++++ OOoPy-1.11/bin/ooo_as_text | 66 ++ OOoPy-1.11/bin/ooo_cat | 61 ++ OOoPy-1.11/bin/ooo_fieldreplace | 65 ++ OOoPy-1.11/bin/ooo_from_csv | 104 ++ OOoPy-1.11/bin/ooo_grep | 32 + OOoPy-1.11/bin/ooo_mailmerge | 69 ++ OOoPy-1.11/bin/ooo_prettyxml | 80 ++ OOoPy-1.11/ooopy/OOoPy.py | 317 ++++++ OOoPy-1.11/ooopy/Transformer.py | 1397 +++++++++++++++++++++++++++ OOoPy-1.11/ooopy/Transforms.py | 1237 ++++++++++++++++++++++++ OOoPy-1.11/ooopy/Version.py | 1 + OOoPy-1.11/ooopy/__init__.py | 0 OOoPy-1.11/run_doctest.py | 94 ++ OOoPy-1.11/setup.py | 88 ++ OOoPy-1.11/testfiles/carta.odt | Bin 0 -> 30000 bytes OOoPy-1.11/testfiles/carta.stw | Bin 0 -> 26692 bytes OOoPy-1.11/testfiles/page1.odt | Bin 0 -> 73235 bytes OOoPy-1.11/testfiles/page2.odt | Bin 0 -> 42093 bytes OOoPy-1.11/testfiles/rechng.odt | Bin 0 -> 14629 bytes OOoPy-1.11/testfiles/rechng.sxw | Bin 0 -> 8963 bytes OOoPy-1.11/testfiles/tbl_first.odt | Bin 0 -> 8547 bytes OOoPy-1.11/testfiles/tbl_second.odt | Bin 0 -> 9475 bytes OOoPy-1.11/testfiles/test.odt | Bin 0 -> 11031 bytes OOoPy-1.11/testfiles/test.sxw | Bin 0 -> 6775 bytes OOoPy-1.11/testfiles/testenum.odt | Bin 0 -> 12284 bytes OOoPy-1.11/testfiles/x.csv | 3 + 29 files changed, 4863 insertions(+) create mode 100644 OOoPy-1.11/PKG-INFO create mode 100644 OOoPy-1.11/README.html create mode 100644 OOoPy-1.11/README.rst create mode 100755 OOoPy-1.11/bin/ooo_as_text create mode 100755 OOoPy-1.11/bin/ooo_cat create mode 100755 OOoPy-1.11/bin/ooo_fieldreplace create mode 100755 OOoPy-1.11/bin/ooo_from_csv create mode 100755 OOoPy-1.11/bin/ooo_grep create mode 100755 OOoPy-1.11/bin/ooo_mailmerge create mode 100755 OOoPy-1.11/bin/ooo_prettyxml create mode 100644 OOoPy-1.11/ooopy/OOoPy.py create mode 100644 OOoPy-1.11/ooopy/Transformer.py create mode 100644 OOoPy-1.11/ooopy/Transforms.py create mode 100644 OOoPy-1.11/ooopy/Version.py create mode 100644 OOoPy-1.11/ooopy/__init__.py create mode 100644 OOoPy-1.11/run_doctest.py create mode 100644 OOoPy-1.11/setup.py create mode 100644 OOoPy-1.11/testfiles/carta.odt create mode 100644 OOoPy-1.11/testfiles/carta.stw create mode 100644 OOoPy-1.11/testfiles/page1.odt create mode 100644 OOoPy-1.11/testfiles/page2.odt create mode 100644 OOoPy-1.11/testfiles/rechng.odt create mode 100644 OOoPy-1.11/testfiles/rechng.sxw create mode 100644 OOoPy-1.11/testfiles/tbl_first.odt create mode 100644 OOoPy-1.11/testfiles/tbl_second.odt create mode 100644 OOoPy-1.11/testfiles/test.odt create mode 100644 OOoPy-1.11/testfiles/test.sxw create mode 100644 OOoPy-1.11/testfiles/testenum.odt create mode 100644 OOoPy-1.11/testfiles/x.csv diff --git a/OOoPy-1.11/PKG-INFO b/OOoPy-1.11/PKG-INFO new file mode 100644 index 0000000..f71d704 --- /dev/null +++ b/OOoPy-1.11/PKG-INFO @@ -0,0 +1,336 @@ +Metadata-Version: 1.1 +Name: OOoPy +Version: 1.11 +Summary: OOoPy: Modify OpenOffice.org documents in Python +Home-page: http://ooopy.sourceforge.net/ +Author: Ralf Schlatterbeck +Author-email: rsc@runtux.com +License: GNU Library or Lesser General Public License (LGPL) +Download-URL: http://downloads.sourceforge.net/project/ooopy/ooopy/1.11/OOoPy-1.11.tar.gz +Description: + OOoPy: Modify OpenOffice.org documents in Python + ================================================ + + :Author: Ralf Schlatterbeck + + OpenOffice.org (OOo) documents are ZIP archives containing several XML + files. Therefore it is easy to inspect, create, or modify OOo + documents. OOoPy is a library in Python for these tasks with OOo + documents. To not reinvent the wheel, OOoPy uses an existing XML + library, ElementTree_ by Fredrik Lundh. OOoPy is a thin wrapper around + ElementTree_ using Python's ZipFile to read and write OOo documents. + + .. _ElementTree: http://effbot.org/zone/element-index.htm + + In addition to being a wrapper for ElementTree_, OOoPy contains a + framework for applying XML transforms to OOo documents. Several + Transforms for OOo documents exist, e.g., for changing OOo fields (OOo + Insert-Fields menu) or using OOo fields for a mail merge application. + Some other transformations for modifying OOo settings and meta + information are also given as examples. + + Applications like this come in handy in applications where calling + native OOo is not an option, e.g., in server-side Web applications. + + If the mailmerge transform doesn't work for your document: The OOo + format is well documented but there are ordering constraints in the body + of an OOo document. + I've not yet figured out all the tags and their order in the + OOo body. Individual elements in an OOo document (like e.g., frames, + sections, tables) need to have their own unique names. After a mailmerge, + there are duplicate names for some items. So far I'm renumbering only + frames, sections, and tables. See the renumber objects at the end of + ooopy/Transforms.py. So if you encounter missing parts of the mailmerged + document, check if there are some renumberings missing or send me a `bug + report`_. + + .. _`bug report`: http://ooopy.sourceforge.net/#reporting-bugs + + There is currently not much documentation except for a python doctest in + OOoPy.py and Transformer.py and the command-line utilities_. + For running these test, after installing + ooopy (assuming here you installed using python into /usr/local):: + + cd /usr/local/share/ooopy + python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/Transformer.py + python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/OOoPy.py + + Both should report no failed tests. + For running the doctest on python2.3 with the metaclass trickery of + autosuper, see the file run_doctest.py. For later versions of python the + bug in doctest is already fixed. + + Usage + ----- + + There were some slight changes to the API when supporting the open + document format introduced with OOo 2.0. See below if you get a traceback + when upgrading from an old version. + + See the online documentation, e.g.:: + + % python + >>> from ooopy.OOoPy import OOoPy + >>> help (OOoPy) + >>> from ooopy.Transformer import Transformer + >>> help (Transformer) + + Help, I'm getting an AssertionError traceback from Transformer, e.g.:: + + Traceback (most recent call last): + File "./replace.py", line 17, in ? + t = Transformer(Field_Replace(replace = replace_dictionary)) + File "/usr/local/lib/python2.4/site-packages/ooopy/Transformer.py", line 1226, in __init__ + assert (mimetype in mimetypes) + AssertionError + + The API changed slightly when implementing handling of different + versions of OOo files. Now the first parameter you pass to the + Transformer constructor is the mimetype of the OpenOffice.org document + you intend to transform. The mimetype can be fetched from another opened + OOo document, e.g.:: + + ooo = OOoPy (infile = 'test.odt', outfile = 'test_out.odt') + t = Transformer(ooo.mimetype, ... + + Usage of Command-Line Utilities + ------------------------------- + + A, well, there are command-line _`utilities` now: + + - ooo_cat for concatenating several OOo files into one + - ooo_grep to do equivalent of grep -l on OOo files -- only runs on + Unix-like operating systems, probably only with the GNU version of grep + (it's a shell-script using ooo_as_text) + - ooo_fieldreplace for replacing fields in an OOo document + - ooo_mailmerge for doing a mailmerge from a template OOo document and a + CSV (comma separated values) input + - ooo_as_text for getting the text from an OOo-File (e.g., for doing a + "grep" on the output). + - ooo_prettyxml for pretty-printing the XML nodes of one of the XML + files inside an OOo document. Mainly useful for debugging. + + All utilities take a ``--help`` option. + + Resources + --------- + + Project information and download from `Sourceforge main page`_ + + .. _`Sourceforge main page`: http://sourceforge.net/projects/ooopy/ + + You need at least version 2.3 of python. + + For using OOoPy with Python versions below 2.5, you need to download and + install the + `ElementTree Library`_ by Fredrik Lundh. For documentation about the OOo + XML file format, see the book by J. David Eisenberg called + `OASIS OpenDocument Essentials`_ which is under the Gnu Free + Documentation License and is also available `in print`_. For a reference + document you may want to check out the `XML File Format Specification`_ + (PDF) by OpenOffice.org. + + A german page for OOoPy exists at `runtux.com`_ + + .. _`ElementTree Library`: http://effbot.org/downloads/#elementtree + .. _`OASIS OpenDocument Essentials`: http://books.evc-cit.info/ + .. _`in print`: + http://www.lulu.com/product/paperback/oasis-opendocument-essentials/392512 + .. _`XML File Format Specification`: + http://xml.openoffice.org/xml_specification.pdf + .. _`runtux.com`: http://www.runtux.com/ooopy.html + + Reporting Bugs + -------------- + Please use the `Sourceforge Bug Tracker`_ and + + - attach the OOo document that reproduces your problem + - give a short description of what you think is the correct behaviour + - give a description of the observed behaviour + - tell me exactly what you did. + + .. _`Sourceforge Bug Tracker`: + http://sourceforge.net/tracker/?group_id=134329&atid=729727 + + Changes + ------- + + Version 1.11: Small Bug fix ooo_mailmerge + + Now ooo_mailmerge uses the delimiter option, it was ignored before. + Thanks to Bob Danek for report and test. + + - Fix setting csv delimiter in ooo_mailmerge + + Version 1.10: Fix table styles when concatenating + + Now ooo_cat fixes tables styles when concatenating (renaming): We + optimize style usage by re-using existing styles. But for some table + styles the original names were not renamed to the re-used ones. + Fixes SF Bug 10, thanks to Claudio Girlanda for reporting. + + - Fix style renaming for table styles when concatenating documents + - Add some missing namespaces (ooo 2009) + + Version 1.9: Add Picture Handling for Concatenation + + Now ooo_cat supports pictures, thanks to Antonio Sánchez for reporting + that this wasn't working. + + - Add a list of filenames + contents to Transformer + - Update this file-list in Concatenate + - Add Manifest_Append transform to update META-INF/manifest.xml with + added filenames + - Add hook in OOoPy for adding files + - Update tests + - Update ooo_cat to use new transform + - This is the first release after migration of the version control from + Subversion to GIT + + Version 1.8: Minor bugfixes + + Distribute a missing file that is used in the doctest. Fix directory + structure. Thanks to Michael Nagel for suggesting the change and + reporting the bug. + + - The file ``testenum.odt`` was missing from MANIFEST.in + - All OOo files and other files needed for testing are now in the + subdirectory ``testfiles``. + - All command line utilities are now in subdirectory ``bin``. + + Version 1.7: Minor feature additions + + Add --newlines option to ooo_as_text: With this option the paragraphs in + the office document are preserved in the text output. + Fix assertion error with python2.7, thanks to Hans-Peter Jansen for the + report. Several other small fixes for python2.7 vs. 2.6. + + - add --newlines option to ooo_as_text + - fix assertion error with python2.7 reported by Hans-Peter Jansen + - fix several deprecation warnings with python2.7 + - remove zip compression sizes from regression test: the compressor in + python2.7 is better than the one in python2.6 + + Version 1.6: Minor bugfixes + + Fix compression: when writing new XML-files these would be stored + instead of compressed in the OOo zip-file resulting in big documents. + Thanks to Hans-Peter Jansen for the patch. Add copyright notice to + command-line utils (SF Bug 2650042). Fix mailmerge for OOo 3.X lists (SF + Bug 2949643). + + - fix compression flag, patch by Hans-Peter Jansen + - add regression test to check for compression + - now release ooo_prettyxml -- I've used this for testing for quite + some time, may be useful to others + - Add copyright (LGPL) notice to command-line utilities, fixes SF Bug + 2650042 + - OOo 3.X adds xml:id tags to lists, we now renumber these in the + mailmerge app., fixes SF Bug 2949643 + + Version 1.5: Minor feature enhancements + + Add ooo_grep to search for OOo files containing a pattern. Thanks to + Mathieu Chauvinc for the reporting the problems with modified + manifest.xml. + Support python2.6, thanks to Erik Myllymaki for reporting and anonymous + contributor(s) for confirming the bug. + + - New shell-script ooo_grep (does equivalent to grep -l on OOo Files) + - On deletion of an OOoPy object close it explicitly (uses __del__) + - Ensure mimetype is the first element in the resulting archive, seems + OOo is picky about this. + - When modifying the manifest the resulting .odt file could not be + opened by OOo. So when modifying manifest make sure the manifest + namespace is named "manifest" not something auto-generated by + ElementTree. I consider this a bug in OOo to require this. This now + uses the _namespace_map of ElementTree and uses the same names as OOo + for all namespaces. The META-INF/manifest.xml is now in the list of + files to which Transforms can be applied. + - When modifying (or creating) archive members, we create the OOo + archive as if it was a DOS system (type fat) and ensure we use the + current date/time (UTC). This also fixes problems with file + permissions on newer versions of pythons ZipFile. + - Fix for python2.6 behavior that __init__ of object may not take any + arguments. Fixes SF Bug 2948617. + - Finally -- since OOoPy is in production in some projects -- change the + development status to "Production/Stable". + + Version 1.4: Minor bugfixes + + Fix Doctest to hopefully run on windows. Thanks to Dani Budinova for + testing thoroughly under windows. + + - Open output-files in "wb" mode instead of "w" in doctest to not + create corrupt OOo documents on windows. + - Use double quotes for arguments when calling system, single quotes + don't seem to work on windows. + - Dont use redirection when calling system, use -i option for input + file instead. Redirection seems to be a problem on windows. + - Explicitly call the python-interpreter, running a script directly is + not supported on windows. + + Version 1.3: Minor bugfixes + + Regression-test failed because some files were not distributed. + Fixes SF Bugs 1970389 and 1972900. + + - Fix MANIFEST.in to include all files needed for regression test + (doctest). + + Version 1.2: Major feature enhancements + + Add ooo_fieldreplace, ooo_cat, ooo_mailmerge command-line utilities. Fix + ooo_as_text to allow specification of output-file. Note that handling of + non-seekable input/output (pipes) for command-line utils will work only + starting with python2.5. Minor bug-fix when concatenating documents. + + - Fix _divide (used for dividing body into parts that must keep + sequence). If one of the sections was empty, body parts would change + sequence. + - Fix handling of cases where we don't have a paragraph (only list) elements + - Implement ooo_cat + - Fix ooo_as_text to include more command-line handling + - Fix reading/writing stdin/stdout for command-line utilities, this + will work reliably (reading/writing non-seekable input/output like, + e.g., pipes) only with python2.5 + - implement ooo_fieldreplace and ooo_mailmerge + + Version 1.1: Minor bugfixes + + Small Documentation changes + + - Fix css stylesheet + - Link to SF logo for Homepage + - Link to other information updated + - Version numbers in documentation fixed + - Add some checks for new API -- first parameter of Transformer is checked now + - Ship files needed for running the doctest and explain how to run it + - Usage section + + Version 1.0: Major feature enhancements + + Now works with version 2.X of OpenOffice.org. Minor API changes. + + - Tested with python 2.3, 2.4, 2.5 + - OOoPy now works for OOo version 1.X and version 2.X + - New attribute mimetype of OOoPy -- this is automatically set when + reading a document, and should be set when writing one. + - renumber_all, get_meta, set_meta are now factory functions that take + the mimetype of the open office document as a parameter. + - Since renumber_all is now a function it will (correctly) restart + numbering for each new Attribute_Access instance it returns. + - Built-in elementtree support from python2.5 is used if available + - Fix bug in optimisation of original document for concatenation + +Platform: Any +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Office/Business :: Office Suites +Classifier: Topic :: Text Processing +Classifier: Topic :: Text Processing :: General +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: Topic :: Text Editors :: Word Processors diff --git a/OOoPy-1.11/README.html b/OOoPy-1.11/README.html new file mode 100644 index 0000000..eeed39a --- /dev/null +++ b/OOoPy-1.11/README.html @@ -0,0 +1,593 @@ + + + + + + + + + + +
+ + +SourceForge.net Logo +
+

OOoPy: Modify OpenOffice.org documents in Python

+ +++ + + + +
Author:Ralf Schlatterbeck <rsc@runtux.com>
+

OpenOffice.org (OOo) documents are ZIP archives containing several XML +files. Therefore it is easy to inspect, create, or modify OOo +documents. OOoPy is a library in Python for these tasks with OOo +documents. To not reinvent the wheel, OOoPy uses an existing XML +library, ElementTree by Fredrik Lundh. OOoPy is a thin wrapper around +ElementTree using Python's ZipFile to read and write OOo documents.

+

In addition to being a wrapper for ElementTree, OOoPy contains a +framework for applying XML transforms to OOo documents. Several +Transforms for OOo documents exist, e.g., for changing OOo fields (OOo +Insert-Fields menu) or using OOo fields for a mail merge application. +Some other transformations for modifying OOo settings and meta +information are also given as examples.

+

Applications like this come in handy in applications where calling +native OOo is not an option, e.g., in server-side Web applications.

+

If the mailmerge transform doesn't work for your document: The OOo +format is well documented but there are ordering constraints in the body +of an OOo document. +I've not yet figured out all the tags and their order in the +OOo body. Individual elements in an OOo document (like e.g., frames, +sections, tables) need to have their own unique names. After a mailmerge, +there are duplicate names for some items. So far I'm renumbering only +frames, sections, and tables. See the renumber objects at the end of +ooopy/Transforms.py. So if you encounter missing parts of the mailmerged +document, check if there are some renumberings missing or send me a bug +report.

+

There is currently not much documentation except for a python doctest in +OOoPy.py and Transformer.py and the command-line utilities. +For running these test, after installing +ooopy (assuming here you installed using python into /usr/local):

+
+cd /usr/local/share/ooopy
+python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/Transformer.py
+python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/OOoPy.py
+
+

Both should report no failed tests. +For running the doctest on python2.3 with the metaclass trickery of +autosuper, see the file run_doctest.py. For later versions of python the +bug in doctest is already fixed.

+
+

Usage

+

There were some slight changes to the API when supporting the open +document format introduced with OOo 2.0. See below if you get a traceback +when upgrading from an old version.

+

See the online documentation, e.g.:

+
+% python
+>>> from ooopy.OOoPy import OOoPy
+>>> help (OOoPy)
+>>> from ooopy.Transformer import Transformer
+>>> help (Transformer)
+
+

Help, I'm getting an AssertionError traceback from Transformer, e.g.:

+
+Traceback (most recent call last):
+  File "./replace.py", line 17, in ?
+    t = Transformer(Field_Replace(replace = replace_dictionary))
+  File "/usr/local/lib/python2.4/site-packages/ooopy/Transformer.py", line 1226, in __init__
+    assert (mimetype in mimetypes)
+AssertionError
+
+

The API changed slightly when implementing handling of different +versions of OOo files. Now the first parameter you pass to the +Transformer constructor is the mimetype of the OpenOffice.org document +you intend to transform. The mimetype can be fetched from another opened +OOo document, e.g.:

+
+ooo = OOoPy (infile = 'test.odt', outfile = 'test_out.odt')
+t = Transformer(ooo.mimetype, ...
+
+
+
+

Usage of Command-Line Utilities

+

A, well, there are command-line utilities now:

+
    +
  • ooo_cat for concatenating several OOo files into one
  • +
  • ooo_grep to do equivalent of grep -l on OOo files -- only runs on +Unix-like operating systems, probably only with the GNU version of grep +(it's a shell-script using ooo_as_text)
  • +
  • ooo_fieldreplace for replacing fields in an OOo document
  • +
  • ooo_mailmerge for doing a mailmerge from a template OOo document and a +CSV (comma separated values) input
  • +
  • ooo_as_text for getting the text from an OOo-File (e.g., for doing a +"grep" on the output).
  • +
  • ooo_prettyxml for pretty-printing the XML nodes of one of the XML +files inside an OOo document. Mainly useful for debugging.
  • +
+

All utilities take a --help option.

+
+
+

Resources

+

Project information and download from Sourceforge main page

+

You need at least version 2.3 of python.

+

For using OOoPy with Python versions below 2.5, you need to download and +install the +ElementTree Library by Fredrik Lundh. For documentation about the OOo +XML file format, see the book by J. David Eisenberg called +OASIS OpenDocument Essentials which is under the Gnu Free +Documentation License and is also available in print. For a reference +document you may want to check out the XML File Format Specification +(PDF) by OpenOffice.org.

+

A german page for OOoPy exists at runtux.com

+
+
+

Reporting Bugs

+

Please use the Sourceforge Bug Tracker and

+
+
    +
  • attach the OOo document that reproduces your problem
  • +
  • give a short description of what you think is the correct behaviour
  • +
  • give a description of the observed behaviour
  • +
  • tell me exactly what you did.
  • +
+
+
+
+

Changes

+

Version 1.11: Small Bug fix ooo_mailmerge

+

Now ooo_mailmerge uses the delimiter option, it was ignored before. +Thanks to Bob Danek for report and test.

+
+
    +
  • Fix setting csv delimiter in ooo_mailmerge
  • +
+
+

Version 1.10: Fix table styles when concatenating

+

Now ooo_cat fixes tables styles when concatenating (renaming): We +optimize style usage by re-using existing styles. But for some table +styles the original names were not renamed to the re-used ones. +Fixes SF Bug 10, thanks to Claudio Girlanda for reporting.

+
+
    +
  • Fix style renaming for table styles when concatenating documents
  • +
  • Add some missing namespaces (ooo 2009)
  • +
+
+

Version 1.9: Add Picture Handling for Concatenation

+

Now ooo_cat supports pictures, thanks to Antonio Sánchez for reporting +that this wasn't working.

+
+
    +
  • Add a list of filenames + contents to Transformer
  • +
  • Update this file-list in Concatenate
  • +
  • Add Manifest_Append transform to update META-INF/manifest.xml with +added filenames
  • +
  • Add hook in OOoPy for adding files
  • +
  • Update tests
  • +
  • Update ooo_cat to use new transform
  • +
  • This is the first release after migration of the version control from +Subversion to GIT
  • +
+
+

Version 1.8: Minor bugfixes

+

Distribute a missing file that is used in the doctest. Fix directory +structure. Thanks to Michael Nagel for suggesting the change and +reporting the bug.

+
+
    +
  • The file testenum.odt was missing from MANIFEST.in
  • +
  • All OOo files and other files needed for testing are now in the +subdirectory testfiles.
  • +
  • All command line utilities are now in subdirectory bin.
  • +
+
+

Version 1.7: Minor feature additions

+

Add --newlines option to ooo_as_text: With this option the paragraphs in +the office document are preserved in the text output. +Fix assertion error with python2.7, thanks to Hans-Peter Jansen for the +report. Several other small fixes for python2.7 vs. 2.6.

+
+
    +
  • add --newlines option to ooo_as_text
  • +
  • fix assertion error with python2.7 reported by Hans-Peter Jansen
  • +
  • fix several deprecation warnings with python2.7
  • +
  • remove zip compression sizes from regression test: the compressor in +python2.7 is better than the one in python2.6
  • +
+
+

Version 1.6: Minor bugfixes

+

Fix compression: when writing new XML-files these would be stored +instead of compressed in the OOo zip-file resulting in big documents. +Thanks to Hans-Peter Jansen for the patch. Add copyright notice to +command-line utils (SF Bug 2650042). Fix mailmerge for OOo 3.X lists (SF +Bug 2949643).

+
+
    +
  • fix compression flag, patch by Hans-Peter Jansen
  • +
  • add regression test to check for compression
  • +
  • now release ooo_prettyxml -- I've used this for testing for quite +some time, may be useful to others
  • +
  • Add copyright (LGPL) notice to command-line utilities, fixes SF Bug +2650042
  • +
  • OOo 3.X adds xml:id tags to lists, we now renumber these in the +mailmerge app., fixes SF Bug 2949643
  • +
+
+

Version 1.5: Minor feature enhancements

+

Add ooo_grep to search for OOo files containing a pattern. Thanks to +Mathieu Chauvinc for the reporting the problems with modified +manifest.xml. +Support python2.6, thanks to Erik Myllymaki for reporting and anonymous +contributor(s) for confirming the bug.

+
+
    +
  • New shell-script ooo_grep (does equivalent to grep -l on OOo Files)
  • +
  • On deletion of an OOoPy object close it explicitly (uses __del__)
  • +
  • Ensure mimetype is the first element in the resulting archive, seems +OOo is picky about this.
  • +
  • When modifying the manifest the resulting .odt file could not be +opened by OOo. So when modifying manifest make sure the manifest +namespace is named "manifest" not something auto-generated by +ElementTree. I consider this a bug in OOo to require this. This now +uses the _namespace_map of ElementTree and uses the same names as OOo +for all namespaces. The META-INF/manifest.xml is now in the list of +files to which Transforms can be applied.
  • +
  • When modifying (or creating) archive members, we create the OOo +archive as if it was a DOS system (type fat) and ensure we use the +current date/time (UTC). This also fixes problems with file +permissions on newer versions of pythons ZipFile.
  • +
  • Fix for python2.6 behavior that __init__ of object may not take any +arguments. Fixes SF Bug 2948617.
  • +
  • Finally -- since OOoPy is in production in some projects -- change the +development status to "Production/Stable".
  • +
+
+

Version 1.4: Minor bugfixes

+

Fix Doctest to hopefully run on windows. Thanks to Dani Budinova for +testing thoroughly under windows.

+
+
    +
  • Open output-files in "wb" mode instead of "w" in doctest to not +create corrupt OOo documents on windows.
  • +
  • Use double quotes for arguments when calling system, single quotes +don't seem to work on windows.
  • +
  • Dont use redirection when calling system, use -i option for input +file instead. Redirection seems to be a problem on windows.
  • +
  • Explicitly call the python-interpreter, running a script directly is +not supported on windows.
  • +
+
+

Version 1.3: Minor bugfixes

+

Regression-test failed because some files were not distributed. +Fixes SF Bugs 1970389 and 1972900.

+
+
    +
  • Fix MANIFEST.in to include all files needed for regression test +(doctest).
  • +
+
+

Version 1.2: Major feature enhancements

+

Add ooo_fieldreplace, ooo_cat, ooo_mailmerge command-line utilities. Fix +ooo_as_text to allow specification of output-file. Note that handling of +non-seekable input/output (pipes) for command-line utils will work only +starting with python2.5. Minor bug-fix when concatenating documents.

+
+
    +
  • Fix _divide (used for dividing body into parts that must keep +sequence). If one of the sections was empty, body parts would change +sequence.
  • +
  • Fix handling of cases where we don't have a paragraph (only list) elements
  • +
  • Implement ooo_cat
  • +
  • Fix ooo_as_text to include more command-line handling
  • +
  • Fix reading/writing stdin/stdout for command-line utilities, this +will work reliably (reading/writing non-seekable input/output like, +e.g., pipes) only with python2.5
  • +
  • implement ooo_fieldreplace and ooo_mailmerge
  • +
+
+

Version 1.1: Minor bugfixes

+

Small Documentation changes

+
+
    +
  • Fix css stylesheet
  • +
  • Link to SF logo for Homepage
  • +
  • Link to other information updated
  • +
  • Version numbers in documentation fixed
  • +
  • Add some checks for new API -- first parameter of Transformer is checked now
  • +
  • Ship files needed for running the doctest and explain how to run it
  • +
  • Usage section
  • +
+
+

Version 1.0: Major feature enhancements

+

Now works with version 2.X of OpenOffice.org. Minor API changes.

+
+
    +
  • Tested with python 2.3, 2.4, 2.5
  • +
  • OOoPy now works for OOo version 1.X and version 2.X
  • +
  • New attribute mimetype of OOoPy -- this is automatically set when +reading a document, and should be set when writing one.
  • +
  • renumber_all, get_meta, set_meta are now factory functions that take +the mimetype of the open office document as a parameter.
  • +
  • Since renumber_all is now a function it will (correctly) restart +numbering for each new Attribute_Access instance it returns.
  • +
  • Built-in elementtree support from python2.5 is used if available
  • +
  • Fix bug in optimisation of original document for concatenation
  • +
+
+
+
+
+ + diff --git a/OOoPy-1.11/README.rst b/OOoPy-1.11/README.rst new file mode 100644 index 0000000..2e645e2 --- /dev/null +++ b/OOoPy-1.11/README.rst @@ -0,0 +1,320 @@ +.. image:: http://sflogo.sourceforge.net/sflogo.php?group_id=134329&type=7 + :height: 62 + :width: 210 + :alt: SourceForge.net Logo + :target: http://sourceforge.net/projects/ooopy/ + +OOoPy: Modify OpenOffice.org documents in Python +================================================ + +:Author: Ralf Schlatterbeck + +OpenOffice.org (OOo) documents are ZIP archives containing several XML +files. Therefore it is easy to inspect, create, or modify OOo +documents. OOoPy is a library in Python for these tasks with OOo +documents. To not reinvent the wheel, OOoPy uses an existing XML +library, ElementTree_ by Fredrik Lundh. OOoPy is a thin wrapper around +ElementTree_ using Python's ZipFile to read and write OOo documents. + +.. _ElementTree: http://effbot.org/zone/element-index.htm + +In addition to being a wrapper for ElementTree_, OOoPy contains a +framework for applying XML transforms to OOo documents. Several +Transforms for OOo documents exist, e.g., for changing OOo fields (OOo +Insert-Fields menu) or using OOo fields for a mail merge application. +Some other transformations for modifying OOo settings and meta +information are also given as examples. + +Applications like this come in handy in applications where calling +native OOo is not an option, e.g., in server-side Web applications. + +If the mailmerge transform doesn't work for your document: The OOo +format is well documented but there are ordering constraints in the body +of an OOo document. +I've not yet figured out all the tags and their order in the +OOo body. Individual elements in an OOo document (like e.g., frames, +sections, tables) need to have their own unique names. After a mailmerge, +there are duplicate names for some items. So far I'm renumbering only +frames, sections, and tables. See the renumber objects at the end of +ooopy/Transforms.py. So if you encounter missing parts of the mailmerged +document, check if there are some renumberings missing or send me a `bug +report`_. + +.. _`bug report`: http://ooopy.sourceforge.net/#reporting-bugs + +There is currently not much documentation except for a python doctest in +OOoPy.py and Transformer.py and the command-line utilities_. +For running these test, after installing +ooopy (assuming here you installed using python into /usr/local):: + + cd /usr/local/share/ooopy + python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/Transformer.py + python run_doctest.py /usr/local/lib/python2.X/site-packages/ooopy/OOoPy.py + +Both should report no failed tests. +For running the doctest on python2.3 with the metaclass trickery of +autosuper, see the file run_doctest.py. For later versions of python the +bug in doctest is already fixed. + +Usage +----- + +There were some slight changes to the API when supporting the open +document format introduced with OOo 2.0. See below if you get a traceback +when upgrading from an old version. + +See the online documentation, e.g.:: + + % python + >>> from ooopy.OOoPy import OOoPy + >>> help (OOoPy) + >>> from ooopy.Transformer import Transformer + >>> help (Transformer) + +Help, I'm getting an AssertionError traceback from Transformer, e.g.:: + + Traceback (most recent call last): + File "./replace.py", line 17, in ? + t = Transformer(Field_Replace(replace = replace_dictionary)) + File "/usr/local/lib/python2.4/site-packages/ooopy/Transformer.py", line 1226, in __init__ + assert (mimetype in mimetypes) + AssertionError + +The API changed slightly when implementing handling of different +versions of OOo files. Now the first parameter you pass to the +Transformer constructor is the mimetype of the OpenOffice.org document +you intend to transform. The mimetype can be fetched from another opened +OOo document, e.g.:: + + ooo = OOoPy (infile = 'test.odt', outfile = 'test_out.odt') + t = Transformer(ooo.mimetype, ... + +Usage of Command-Line Utilities +------------------------------- + +A, well, there are command-line _`utilities` now: + +- ooo_cat for concatenating several OOo files into one +- ooo_grep to do equivalent of grep -l on OOo files -- only runs on + Unix-like operating systems, probably only with the GNU version of grep + (it's a shell-script using ooo_as_text) +- ooo_fieldreplace for replacing fields in an OOo document +- ooo_mailmerge for doing a mailmerge from a template OOo document and a + CSV (comma separated values) input +- ooo_as_text for getting the text from an OOo-File (e.g., for doing a + "grep" on the output). +- ooo_prettyxml for pretty-printing the XML nodes of one of the XML + files inside an OOo document. Mainly useful for debugging. + +All utilities take a ``--help`` option. + +Resources +--------- + +Project information and download from `Sourceforge main page`_ + +.. _`Sourceforge main page`: http://sourceforge.net/projects/ooopy/ + +You need at least version 2.3 of python. + +For using OOoPy with Python versions below 2.5, you need to download and +install the +`ElementTree Library`_ by Fredrik Lundh. For documentation about the OOo +XML file format, see the book by J. David Eisenberg called +`OASIS OpenDocument Essentials`_ which is under the Gnu Free +Documentation License and is also available `in print`_. For a reference +document you may want to check out the `XML File Format Specification`_ +(PDF) by OpenOffice.org. + +A german page for OOoPy exists at `runtux.com`_ + +.. _`ElementTree Library`: http://effbot.org/downloads/#elementtree +.. _`OASIS OpenDocument Essentials`: http://books.evc-cit.info/ +.. _`in print`: + http://www.lulu.com/product/paperback/oasis-opendocument-essentials/392512 +.. _`XML File Format Specification`: + http://xml.openoffice.org/xml_specification.pdf +.. _`runtux.com`: http://www.runtux.com/ooopy.html + +Reporting Bugs +-------------- +Please use the `Sourceforge Bug Tracker`_ and + + - attach the OOo document that reproduces your problem + - give a short description of what you think is the correct behaviour + - give a description of the observed behaviour + - tell me exactly what you did. + +.. _`Sourceforge Bug Tracker`: + http://sourceforge.net/tracker/?group_id=134329&atid=729727 + +Changes +------- + +Version 1.11: Small Bug fix ooo_mailmerge + +Now ooo_mailmerge uses the delimiter option, it was ignored before. +Thanks to Bob Danek for report and test. + + - Fix setting csv delimiter in ooo_mailmerge + +Version 1.10: Fix table styles when concatenating + +Now ooo_cat fixes tables styles when concatenating (renaming): We +optimize style usage by re-using existing styles. But for some table +styles the original names were not renamed to the re-used ones. +Fixes SF Bug 10, thanks to Claudio Girlanda for reporting. + + - Fix style renaming for table styles when concatenating documents + - Add some missing namespaces (ooo 2009) + +Version 1.9: Add Picture Handling for Concatenation + +Now ooo_cat supports pictures, thanks to Antonio Sánchez for reporting +that this wasn't working. + + - Add a list of filenames + contents to Transformer + - Update this file-list in Concatenate + - Add Manifest_Append transform to update META-INF/manifest.xml with + added filenames + - Add hook in OOoPy for adding files + - Update tests + - Update ooo_cat to use new transform + - This is the first release after migration of the version control from + Subversion to GIT + +Version 1.8: Minor bugfixes + +Distribute a missing file that is used in the doctest. Fix directory +structure. Thanks to Michael Nagel for suggesting the change and +reporting the bug. + + - The file ``testenum.odt`` was missing from MANIFEST.in + - All OOo files and other files needed for testing are now in the + subdirectory ``testfiles``. + - All command line utilities are now in subdirectory ``bin``. + +Version 1.7: Minor feature additions + +Add --newlines option to ooo_as_text: With this option the paragraphs in +the office document are preserved in the text output. +Fix assertion error with python2.7, thanks to Hans-Peter Jansen for the +report. Several other small fixes for python2.7 vs. 2.6. + + - add --newlines option to ooo_as_text + - fix assertion error with python2.7 reported by Hans-Peter Jansen + - fix several deprecation warnings with python2.7 + - remove zip compression sizes from regression test: the compressor in + python2.7 is better than the one in python2.6 + +Version 1.6: Minor bugfixes + +Fix compression: when writing new XML-files these would be stored +instead of compressed in the OOo zip-file resulting in big documents. +Thanks to Hans-Peter Jansen for the patch. Add copyright notice to +command-line utils (SF Bug 2650042). Fix mailmerge for OOo 3.X lists (SF +Bug 2949643). + + - fix compression flag, patch by Hans-Peter Jansen + - add regression test to check for compression + - now release ooo_prettyxml -- I've used this for testing for quite + some time, may be useful to others + - Add copyright (LGPL) notice to command-line utilities, fixes SF Bug + 2650042 + - OOo 3.X adds xml:id tags to lists, we now renumber these in the + mailmerge app., fixes SF Bug 2949643 + +Version 1.5: Minor feature enhancements + +Add ooo_grep to search for OOo files containing a pattern. Thanks to +Mathieu Chauvinc for the reporting the problems with modified +manifest.xml. +Support python2.6, thanks to Erik Myllymaki for reporting and anonymous +contributor(s) for confirming the bug. + + - New shell-script ooo_grep (does equivalent to grep -l on OOo Files) + - On deletion of an OOoPy object close it explicitly (uses __del__) + - Ensure mimetype is the first element in the resulting archive, seems + OOo is picky about this. + - When modifying the manifest the resulting .odt file could not be + opened by OOo. So when modifying manifest make sure the manifest + namespace is named "manifest" not something auto-generated by + ElementTree. I consider this a bug in OOo to require this. This now + uses the _namespace_map of ElementTree and uses the same names as OOo + for all namespaces. The META-INF/manifest.xml is now in the list of + files to which Transforms can be applied. + - When modifying (or creating) archive members, we create the OOo + archive as if it was a DOS system (type fat) and ensure we use the + current date/time (UTC). This also fixes problems with file + permissions on newer versions of pythons ZipFile. + - Fix for python2.6 behavior that __init__ of object may not take any + arguments. Fixes SF Bug 2948617. + - Finally -- since OOoPy is in production in some projects -- change the + development status to "Production/Stable". + +Version 1.4: Minor bugfixes + +Fix Doctest to hopefully run on windows. Thanks to Dani Budinova for +testing thoroughly under windows. + + - Open output-files in "wb" mode instead of "w" in doctest to not + create corrupt OOo documents on windows. + - Use double quotes for arguments when calling system, single quotes + don't seem to work on windows. + - Dont use redirection when calling system, use -i option for input + file instead. Redirection seems to be a problem on windows. + - Explicitly call the python-interpreter, running a script directly is + not supported on windows. + +Version 1.3: Minor bugfixes + +Regression-test failed because some files were not distributed. +Fixes SF Bugs 1970389 and 1972900. + + - Fix MANIFEST.in to include all files needed for regression test + (doctest). + +Version 1.2: Major feature enhancements + +Add ooo_fieldreplace, ooo_cat, ooo_mailmerge command-line utilities. Fix +ooo_as_text to allow specification of output-file. Note that handling of +non-seekable input/output (pipes) for command-line utils will work only +starting with python2.5. Minor bug-fix when concatenating documents. + + - Fix _divide (used for dividing body into parts that must keep + sequence). If one of the sections was empty, body parts would change + sequence. + - Fix handling of cases where we don't have a paragraph (only list) elements + - Implement ooo_cat + - Fix ooo_as_text to include more command-line handling + - Fix reading/writing stdin/stdout for command-line utilities, this + will work reliably (reading/writing non-seekable input/output like, + e.g., pipes) only with python2.5 + - implement ooo_fieldreplace and ooo_mailmerge + +Version 1.1: Minor bugfixes + +Small Documentation changes + + - Fix css stylesheet + - Link to SF logo for Homepage + - Link to other information updated + - Version numbers in documentation fixed + - Add some checks for new API -- first parameter of Transformer is checked now + - Ship files needed for running the doctest and explain how to run it + - Usage section + +Version 1.0: Major feature enhancements + +Now works with version 2.X of OpenOffice.org. Minor API changes. + + - Tested with python 2.3, 2.4, 2.5 + - OOoPy now works for OOo version 1.X and version 2.X + - New attribute mimetype of OOoPy -- this is automatically set when + reading a document, and should be set when writing one. + - renumber_all, get_meta, set_meta are now factory functions that take + the mimetype of the open office document as a parameter. + - Since renumber_all is now a function it will (correctly) restart + numbering for each new Attribute_Access instance it returns. + - Built-in elementtree support from python2.5 is used if available + - Fix bug in optimisation of original document for concatenation diff --git a/OOoPy-1.11/bin/ooo_as_text b/OOoPy-1.11/bin/ooo_as_text new file mode 100755 index 0000000..42e2af5 --- /dev/null +++ b/OOoPy-1.11/bin/ooo_as_text @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# Copyright (C) 2007-10 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from optparse import OptionParser +from StringIO import StringIO +from ooopy.OOoPy import OOoPy +from ooopy.Transforms import OOo_Tag + +def as_text (node, out, mimetype, newlines=False) : + if node.text is not None : + print >> out, node.text.encode ('utf-8'), + for subnode in node : + as_text (subnode, out, mimetype, newlines) + if node.tail is not None : + print >> out, node.tail.encode ('utf-8'), + if newlines and node.tag == OOo_Tag ('text', 'p', mimetype) : + print >> out, "" + + +if __name__ == '__main__' : + usage = '%prog [-o|--output-file ] [file, ...]' + parser = OptionParser (usage = usage) + parser.add_option \ + ( "-o", "--output-file" + , dest = "output_file" + , help = "Output file (defaults to stdout)" + , default = None + ) + parser.add_option \ + ( "-n", "--newlines" + , help = "Add newlines after paragraphs" + , action = "store_true" + ) + (options, args) = parser.parse_args () + if options.output_file is None : + outfile = sys.stdout + else : + outfile = open (options.output_file, "w") + if len (args) < 1 : + infiles = [StringIO (sys.stdin.read ())] + else : + infiles = args + for f in infiles : + o = OOoPy (infile = f) + e = o.read ('content.xml') + as_text (e.getroot (), outfile, o.mimetype, options.newlines) diff --git a/OOoPy-1.11/bin/ooo_cat b/OOoPy-1.11/bin/ooo_cat new file mode 100755 index 0000000..29bba0d --- /dev/null +++ b/OOoPy-1.11/bin/ooo_cat @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Copyright (C) 2008-14 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from optparse import OptionParser +from StringIO import StringIO +from ooopy.OOoPy import OOoPy +from ooopy.Transformer import Transformer +import ooopy.Transforms as Transforms + +if __name__ == '__main__' : + usage = '%prog [-o|--output-file ] [file, ...]' + parser = OptionParser (usage = usage) + parser.add_option \ + ( "-o", "--output-file" + , dest = "output_file" + , help = "Output file (defaults to stdout)" + , default = None + ) + (options, args) = parser.parse_args () + if len (args) < 1 : + infiles = [StringIO (sys.stdin.read ())] + else : + infiles = args + outfile = options.output_file + if outfile is None : + outfile = StringIO () + o = OOoPy (infile = infiles [0], outfile = outfile) + if len (infiles) > 1 : + t = Transformer \ + ( o.mimetype + , Transforms.get_meta (o.mimetype) + , Transforms.Concatenate (* (infiles [1:])) + , Transforms.renumber_all (o.mimetype) + , Transforms.set_meta (o.mimetype) + , Transforms.Fix_OOo_Tag () + , Transforms.Manifest_Append () + ) + t.transform (o) + o.close () + if options.output_file is None : + sys.stdout.write (outfile.getvalue ()) diff --git a/OOoPy-1.11/bin/ooo_fieldreplace b/OOoPy-1.11/bin/ooo_fieldreplace new file mode 100755 index 0000000..4b2fd00 --- /dev/null +++ b/OOoPy-1.11/bin/ooo_fieldreplace @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# Copyright (C) 2008-10 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from optparse import OptionParser +from StringIO import StringIO +from ooopy.OOoPy import OOoPy +from ooopy.Transformer import Transformer +import ooopy.Transforms as Transforms + +if __name__ == '__main__' : + usage = \ + '''%prog [-i|--input-file ] + [-o|--output-file ] [name=value, ...]''' + parser = OptionParser (usage = usage) + parser.add_option \ + ( "-i", "--input-file" + , dest = "input_file" + , help = "Input file (defaults to stdin)" + , default = None + ) + parser.add_option \ + ( "-o", "--output-file" + , dest = "output_file" + , help = "Output file (defaults to stdout)" + , default = None + ) + (options, args) = parser.parse_args () + fields = dict (arg.split ('=', 1) for arg in args) + infile = options.input_file + outfile = options.output_file + if infile is None : + infile = StringIO (sys.stdin.read ()) + if outfile is None : + outfile = StringIO () + o = OOoPy (infile = infile, outfile = outfile) + t = Transformer \ + ( o.mimetype + , Transforms.Editinfo () + , Transforms.Field_Replace (replace = fields) + , Transforms.Fix_OOo_Tag () + ) + t.transform (o) + o.close () + if options.output_file is None : + sys.stdout.write (outfile.getvalue ()) diff --git a/OOoPy-1.11/bin/ooo_from_csv b/OOoPy-1.11/bin/ooo_from_csv new file mode 100755 index 0000000..6b205cc --- /dev/null +++ b/OOoPy-1.11/bin/ooo_from_csv @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from csv import reader +from optparse import OptionParser +from StringIO import StringIO +from ooopy.OOoPy import OOoPy, OOoElementTree, mimetypes +from ooopy.Transformer import OOo_Tag +from ooopy.Transforms import Element, SubElement + +def from_csv (ooopy, incsv) : + """ Produce ElementTree from the CSV, then convert the Tree to the + content.csv file inside the given ooopy container + """ + mt = mimetypes [1] + root = Element (OOo_Tag ('office', 'document-content', mt)) + body = SubElement (root, OOo_Tag ('office', 'body', mt)) + #scrpt = SubElement (body, OOo_Tag ('office', 'scripts')) + #decl = SubElement (body, OOo_Tag ('office', 'font-face-decls')) + sheet = SubElement (body, OOo_Tag ('office', 'spreadsheet', mt)) + table = SubElement (sheet, OOo_Tag ('table', 'table', mt), name = 'Sheet1') + tree = OOoElementTree (ooopy, 'content.xml', root) + for line in incsv : + row = SubElement (table, OOo_Tag ('table', 'table-row', mt)) + for element in line : + cell = SubElement \ + ( row + , OOo_Tag ('table', 'table-cell', mt) + , {OOo_Tag ('office', 'value-type', mt) : "string"} + ) + p = SubElement (cell, OOo_Tag ('text', 'p', mt)) + p.text = element + tree.write () + # Add META-INF/manifest.xml + root = Element (OOo_Tag ('manifest', 'manifest', mt)) + SubElement \ + ( root, OOo_Tag ('manifest', 'file-entry', mt) + , { OOo_Tag ('manifest', 'media-type', mt) : + 'application/vnd.oasis.opendocument.spreadsheet' + , OOo_Tag ('manifest', 'full-path', mt) : '/' + } + ) + SubElement \ + ( root, OOo_Tag ('manifest', 'file-entry', mt) + , { OOo_Tag ('manifest', 'media-type', mt) : 'text/xml' + , OOo_Tag ('manifest', 'full-path', mt) : 'content.xml' + } + ) + tree = OOoElementTree (ooopy, 'META-INF/manifest.xml', root) + tree.write () +# end def from_csv + +if __name__ == '__main__' : + parser = OptionParser () + parser.add_option \ + ( "-i", "--input-file" + , dest = "input_file" + , help = "CSV Input file (defaults to stdin)" + , default = None + ) + parser.add_option \ + ( "-o", "--output-file" + , dest = "output_file" + , help = "Output file (defaults to stdout)" + , default = None + ) + parser.add_option \ + ( "-d", "--delimiter" + , help = "Delimiter of CSV file" + , default = ',' + ) + (opt, args) = parser.parse_args () + outfile = opt.output_file + if opt.input_file : + incsv = reader (open (opt.input_file), delimiter = opt.delimiter) + else : + incsv = reader (sys.stdin, delimiter = opt.delimiter) + if outfile is None : + outfile = StringIO () + o = OOoPy (outfile = outfile, mimetype = mimetypes [1]) + from_csv (o, incsv) + o.close () + if opt.output_file is None : + sys.stdout.write (outfile.getvalue ()) diff --git a/OOoPy-1.11/bin/ooo_grep b/OOoPy-1.11/bin/ooo_grep new file mode 100755 index 0000000..721c36e --- /dev/null +++ b/OOoPy-1.11/bin/ooo_grep @@ -0,0 +1,32 @@ +#!/bin/sh +# Copyright (C) 2008-10 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +# Run all given ooo files through ooo_as_text and grep -l for pattern +if [ $# -lt 2 ] ; then + echo "Usage: $0 ..." 2>&1 + exit 42 +fi +pattern=$1 +shift +for k in "$@" ; do + ooo_as_text "$k" | grep -l --label="$k" "$pattern" +done diff --git a/OOoPy-1.11/bin/ooo_mailmerge b/OOoPy-1.11/bin/ooo_mailmerge new file mode 100755 index 0000000..680670e --- /dev/null +++ b/OOoPy-1.11/bin/ooo_mailmerge @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Copyright (C) 2008-10 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from optparse import OptionParser +from csv import DictReader +from StringIO import StringIO +from ooopy.OOoPy import OOoPy +from ooopy.Transformer import Transformer +import ooopy.Transforms as Transforms + +if __name__ == '__main__' : + usage = \ + '''%prog [-d|--delimiter X] [-o|--output-file ] + ''' + parser = OptionParser (usage = usage) + parser.add_option \ + ( "-d", "--delimiter" + , dest = "delimiter" + , help = "Delimiter of cvs-format (Default Tab)" + , default = '\t' + ) + parser.add_option \ + ( "-o", "--output-file" + , dest = "output_file" + , help = "Output file (defaults to stdout)" + , default = None + ) + (options, args) = parser.parse_args () + if len (args) != 2 : + parser.error ('Missing arguments') + sys.exit (1) + outfile = options.output_file + if outfile is None : + outfile = StringIO () + d = DictReader (open (args [1]), delimiter = options.delimiter) + o = OOoPy (infile = args [0], outfile = outfile) + t = Transformer \ + ( o.mimetype + , Transforms.get_meta (o.mimetype) + , Transforms.Addpagebreak_Style () + , Transforms.Mailmerge (iterator = d) + , Transforms.renumber_all (o.mimetype) + , Transforms.set_meta (o.mimetype) + , Transforms.Fix_OOo_Tag () + ) + t.transform (o) + o.close () + if options.output_file is None : + sys.stdout.write (outfile.getvalue ()) diff --git a/OOoPy-1.11/bin/ooo_prettyxml b/OOoPy-1.11/bin/ooo_prettyxml new file mode 100755 index 0000000..afc904d --- /dev/null +++ b/OOoPy-1.11/bin/ooo_prettyxml @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# Copyright (C) 2005-10 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +import sys +from optparse import OptionParser +from ooopy.OOoPy import OOoPy +from ooopy.Transformer import split_tag + +def cleantag (tag) : + return ':'.join (split_tag (tag)) + +def pretty (n, indent = 0, with_text = False, ext_ns = False) : + s = [" " * indent] + clean = cleantag + if ext_ns : + clean = lambda x : x + s.append (clean (n.tag)) + attrkeys = n.attrib.keys () + attrkeys.sort () + for a in attrkeys : + s.append (' %s="%s"' % (clean (a), n.attrib [a])) + if with_text and n.text is not None : + s.append (' TEXT="%s"' % n.text) + if with_text and n.tail is not None : + s.append (' TAIL="%s"' % n.tail) + print ''.join (s).encode ('utf-8') + for sub in n : + pretty (sub, indent + 1, with_text, ext_ns) + +if __name__ == '__main__' : + usage = "%prog [options] file ..." + parser = OptionParser (usage = usage) + parser.add_option \ + ( "-f", "--file" + , dest = "ooofile" + , help = "XML-File inside OOo File" + , default = 'content.xml' + ) + parser.add_option \ + ( "-t", "--with-text" + , dest = "with_text" + , action = "store_true" + , help = "Print text of xml nodes" + , default = False + ) + parser.add_option \ + ( "-x", "--extend_namespaces" + , dest = "ext_ns" + , action = "store_true" + , help = "Print full text of namespace name" + , default = False + ) + (opt, args) = parser.parse_args () + if len (args) < 1 : + parser.print_help (sys.stderr) + sys.exit (23) + for f in args : + o = OOoPy (infile = f) + e = o.read (opt.ooofile) + pretty (e.getroot (), with_text = opt.with_text, ext_ns = opt.ext_ns) + o.close () diff --git a/OOoPy-1.11/ooopy/OOoPy.py b/OOoPy-1.11/ooopy/OOoPy.py new file mode 100644 index 0000000..87e0b81 --- /dev/null +++ b/OOoPy-1.11/ooopy/OOoPy.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2005-14 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +from __future__ import absolute_import + +from zipfile import ZipFile, ZIP_DEFLATED, ZipInfo +try : + from StringIO import StringIO +except ImportError : + from io import StringIO +from datetime import datetime +try : + from xml.etree.ElementTree import ElementTree, fromstring, _namespace_map +except ImportError : + from elementtree.ElementTree import ElementTree, fromstring, _namespace_map +from tempfile import mkstemp +from ooopy.Version import VERSION +import os + +class _autosuper (type) : + def __init__ (cls, name, bases, dict) : + super (_autosuper, cls).__init__ (name, bases, dict) + setattr (cls, "_%s__super" % name, super (cls)) + # end def __init__ +# end class _autosuper + +class autosuper (object) : + __metaclass__ = _autosuper + def __init__ (self, *args, **kw) : + self.__super.__init__ () + # end def __init__ +# end class autosuper + +files = \ + [ 'content.xml' + , 'styles.xml' + , 'meta.xml' + , 'settings.xml' + , 'META-INF/manifest.xml' + ] + +mimetypes = \ + [ 'application/vnd.sun.xml.writer' + , 'application/vnd.oasis.opendocument.text' + ] +namespace_by_name = \ + { mimetypes [0] : + { 'chart' : "http://openoffice.org/2000/chart" + , 'config' : "http://openoffice.org/2001/config" + , 'dc' : "http://purl.org/dc/elements/1.1/" + , 'dr3d' : "http://openoffice.org/2000/dr3d" + , 'draw' : "http://openoffice.org/2000/drawing" + , 'fo' : "http://www.w3.org/1999/XSL/Format" + , 'form' : "http://openoffice.org/2000/form" + , 'math' : "http://www.w3.org/1998/Math/MathML" + , 'meta' : "http://openoffice.org/2000/meta" + , 'number' : "http://openoffice.org/2000/datastyle" + , 'office' : "http://openoffice.org/2000/office" + , 'script' : "http://openoffice.org/2000/script" + , 'style' : "http://openoffice.org/2000/style" + , 'svg' : "http://www.w3.org/2000/svg" + , 'table' : "http://openoffice.org/2000/table" + , 'text' : "http://openoffice.org/2000/text" + , 'xlink' : "http://www.w3.org/1999/xlink" + , 'manifest' : "http://openoffice.org/2001/manifest" + } + , mimetypes [1] : + { 'chart' : "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + , 'config' : "urn:oasis:names:tc:opendocument:xmlns:config:1.0" + , 'dc' : "http://purl.org/dc/elements/1.1/" + , 'dr3d' : "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + , 'draw' : "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + , 'fo' : "urn:oasis:names:tc:opendocument:xmlns:" + "xsl-fo-compatible:1.0" + , 'form' : "urn:oasis:names:tc:opendocument:xmlns:form:1.0" + , 'math' : "http://www.w3.org/1998/Math/MathML" + , 'meta' : "urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + , 'number' : "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + , 'office' : "urn:oasis:names:tc:opendocument:xmlns:office:1.0" + , 'officeooo': "http://openoffice.org/2009/office" + , 'script' : "urn:oasis:names:tc:opendocument:xmlns:script:1.0" + , 'style' : "urn:oasis:names:tc:opendocument:xmlns:style:1.0" + , 'svg' : "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + , 'table' : "urn:oasis:names:tc:opendocument:xmlns:table:1.0" + , 'text' : "urn:oasis:names:tc:opendocument:xmlns:text:1.0" + , 'xlink' : "http://www.w3.org/1999/xlink" + , 'manifest' : "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" + , 'tableooo' : "http://openoffice.org/2009/table" + , 'transformation' : "http://www.w3.org/2003/g/data-view#" + # OOo 1.X tags and some others: + , 'ooo' : "http://openoffice.org/2004/office" + , 'ooow' : "http://openoffice.org/2004/writer" + , 'oooc' : "http://openoffice.org/2004/calc" + , 'o_dom' : "http://www.w3.org/2001/xml-events" + , 'o_xforms' : "http://www.w3.org/2002/xforms" + , 'xs' : "http://www.w3.org/2001/XMLSchema" + , 'xsi' : "http://www.w3.org/2001/XMLSchema-instance" + # predefined xml namespace, see + # http://www.w3.org/TR/2006/REC-xml-names11-20060816/ + # "It MAY, but need not, be declared, and MUST NOT be undeclared + # or bound to any other namespace name." + , 'xml' : "http://www.w3.org/XML/1998/namespace" + } + } + +for mimetype in namespace_by_name.itervalues () : + for k, v in mimetype.iteritems () : + if v in _namespace_map : + assert (_namespace_map [v] == k) + _namespace_map [v] = k + +class OOoElementTree (autosuper) : + """ + An ElementTree for OOo document XML members. Behaves like the + orginal ElementTree (in fact it delegates almost everything to a + real instance of ElementTree) except for the write method, that + writes itself back to the OOo XML file in the OOo zip archive it + came from. + """ + def __init__ (self, ooopy, zname, root) : + self.ooopy = ooopy + self.zname = zname + self.tree = ElementTree (root) + # end def __init__ + + def write (self) : + self.ooopy.write (self.zname, self.tree) + # end def write + + def __getattr__ (self, name) : + """ + Delegate everything to our ElementTree attribute. + """ + if not name.startswith ('__') : + result = getattr (self.tree, name) + setattr (self, name, result) + return result + raise AttributeError (name) + # end def __getattr__ + +# end class OOoElementTree + +class OOoPy (autosuper) : + """ + Wrapper for OpenOffice.org zip files (all OOo documents are + really zip files internally). + + from ooopy.OOoPy import OOoPy + >>> o = OOoPy (infile = 'testfiles/test.sxw', outfile = 'out.sxw') + >>> o.mimetype + 'application/vnd.sun.xml.writer' + >>> for f in files : + ... e = o.read (f) + ... e.write () + ... + >>> o.close () + >>> o = OOoPy (infile = 'testfiles/test.odt', outfile = 'out2.odt') + >>> o.mimetype + 'application/vnd.oasis.opendocument.text' + >>> for f in files : + ... e = o.read (f) + ... e.write () + ... + >>> o.append_file ('Pictures/empty', '') + >>> o.close () + >>> o = OOoPy (infile = 'out2.odt') + >>> for f in o.izip.infolist () : + ... print f.filename, f.create_system, f.compress_type + mimetype 0 8 + content.xml 0 8 + styles.xml 0 8 + meta.xml 0 8 + settings.xml 0 8 + META-INF/manifest.xml 0 8 + Pictures/empty 0 8 + Configurations2/statusbar/ 0 0 + Configurations2/accelerator/current.xml 0 8 + Configurations2/floater/ 0 0 + Configurations2/popupmenu/ 0 0 + Configurations2/progressbar/ 0 0 + Configurations2/menubar/ 0 0 + Configurations2/toolbar/ 0 0 + Configurations2/images/Bitmaps/ 0 0 + Thumbnails/thumbnail.png 0 8 + """ + def __init__ \ + ( self + , infile = None + , outfile = None + , write_mode = 'w' + , mimetype = None + ) : + """ + Open an OOo document, if no outfile is given, we open the + file read-only. Otherwise the outfile has to be different + from the infile -- the python ZipFile can't deal with + read-write access. In case an outfile is given, we open it + in "w" mode as a zip file, unless write_mode is specified + (the only allowed case would be "a" for appending to an + existing file, see pythons ZipFile documentation for + details). If no infile is given, the user is responsible for + providing all necessary files in the resulting output file. + + It seems that OOo needs to have the mimetype as the first + archive member (at least with mimetype as the first member + it works, the order may not be arbitrary) to recognize a zip + archive as an OOo file. When copying from a given infile, we + use the same order of elements in the resulting output. When + creating new elements we make sure the mimetype is the first + in the resulting archive. + + Note that both, infile and outfile can either be filenames + or file-like objects (e.g. StringIO). + + The mimetype is automatically determined if an infile is + given. If only writing is desired, the mimetype should be + set. + """ + assert (infile != outfile) + self.izip = self.ozip = None + if infile : + self.izip = ZipFile (infile, 'r', ZIP_DEFLATED) + if outfile : + self.ozip = ZipFile (outfile, write_mode, ZIP_DEFLATED) + self.written = {} + if mimetype : + self.mimetype = mimetype + elif self.izip : + self.mimetype = self.izip.read ('mimetype') + # end def __init__ + + def read (self, zname) : + """ + return an OOoElementTree object for the given OOo document + archive member name. Currently an OOo document contains the + following XML files:: + + * content.xml: the text of the OOo document + * styles.xml: style definitions + * meta.xml: meta-information (author, last changed, ...) + * settings.xml: settings in OOo + * META-INF/manifest.xml: contents of the archive + + There is an additional file "mimetype" that always contains + the string "application/vnd.sun.xml.writer" for OOo 1.X files + and the string "application/vnd.oasis.opendocument.text" for + OOo 2.X files. + """ + assert (self.izip) + return OOoElementTree (self, zname, fromstring (self.izip.read (zname))) + # end def read + + def _write (self, zname, str) : + now = datetime.utcnow ().timetuple () + info = ZipInfo (zname, date_time = now) + info.create_system = 0 # pretend to be fat + info.compress_type = ZIP_DEFLATED + self.ozip.writestr (info, str) + self.written [zname] = 1 + # end def _write + + def write (self, zname, etree) : + assert (self.ozip) + # assure mimetype is the first member in new archive + if 'mimetype' not in self.written : + self._write ('mimetype', self.mimetype) + str = StringIO () + etree.write (str) + self._write (zname, str.getvalue ()) + # end def write + + def append_file (self, zname, str) : + """ Official interface to _write: Append a file to the end of + the archive. + """ + if zname not in self.written : + self._write (zname, str) + # end def append_file + + def close (self) : + """ + Close the zip files. According to documentation of zipfile in + the standard python lib, this has to be done to be sure + everything is written. We copy over the not-yet written files + from izip before closing ozip. + """ + if self.izip and self.ozip : + for f in self.izip.infolist () : + if f.filename not in self.written : + self.ozip.writestr (f, self.izip.read (f.filename)) + for i in self.izip, self.ozip : + if i : i.close () + self.izip = self.ozip = None + # end def close + + __del__ = close # auto-close on deletion of object +# end class OOoPy diff --git a/OOoPy-1.11/ooopy/Transformer.py b/OOoPy-1.11/ooopy/Transformer.py new file mode 100644 index 0000000..dbbab12 --- /dev/null +++ b/OOoPy-1.11/ooopy/Transformer.py @@ -0,0 +1,1397 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2005-14 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +from __future__ import absolute_import + +import time +import re +try : + from xml.etree.ElementTree import dump, SubElement, Element, tostring + from xml.etree.ElementTree import _namespace_map +except ImportError : + from elementtree.ElementTree import dump, SubElement, Element, tostring + from elementtree.ElementTree import _namespace_map +from copy import deepcopy +from ooopy.OOoPy import OOoPy, autosuper +from ooopy.OOoPy import files, mimetypes, namespace_by_name +from ooopy.Version import VERSION + +def OOo_Tag (namespace, name, mimetype) : + """Return combined XML tag + + >>> OOo_Tag ('xml', 'id', mimetypes [1]) + '{http://www.w3.org/XML/1998/namespace}id' + >>> OOo_Tag ('text', 'list', mimetypes [1]) + '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list' + """ + return "{%s}%s" % (namespace_by_name [mimetype][namespace], name) +# end def OOo_Tag + +def split_tag (tag) : + """ Split tag into symbolic namespace and name part -- inverse + operation of OOo_Tag. + """ + ns, t = tag.split ('}') + return (_namespace_map [ns [1:]], t) +# end def split_tag + +class Transform (autosuper) : + """ + Base class for individual transforms on OOo files. An individual + transform needs a filename variable for specifying the OOo file + the transform should be applied to and an optional prio. + Individual transforms are applied according to their prio + setting, higher prio means later application of a transform. + + The filename variable must specify one of the XML files which are + part of the OOo document (see files variable above). As + the names imply, content.xml contains the contents of the + document (text and ad-hoc style definitions), styles.xml contains + the style definitions, meta.xml contains meta information like + author, editing time, etc. and settings.xml is used to store + OOo's settings (menu Tools->Configure). + """ + prio = 100 + textbody_names = \ + { mimetypes [0] : 'body' + , mimetypes [1] : 'text' + } + paragraph_props = \ + { mimetypes [0] : 'properties' + , mimetypes [1] : 'paragraph-properties' + } + font_decls = \ + { mimetypes [0] : 'font-decls' + , mimetypes [1] : 'font-face-decls' + } + + def __init__ (self, prio = None, transformer = None) : + if prio is not None : + self.prio = prio + self.transformer = None + if transformer : + self.register (transformer) + # end def __init__ + + def apply (self, root) : + """ Apply myself to the element given as root """ + raise NotImplementedError, 'derived transforms must implement "apply"' + # end def apply + + def apply_all (self, trees) : + """ Apply myself to all the files given in trees. The variable + trees contains a dictionary of ElementTree indexed by the + name of the OOo File. + The standard case is that only one file (namely + self.filename) is used. + """ + assert (self.filename) + self.apply (trees [self.filename].getroot ()) + # end def apply_all + + def find_tbody (self, root) : + """ Find the node which really contains the text -- different + for different OOo versions. + """ + tbody = root + if tbody.tag != self.textbody_tag : + tbody = tbody.find ('.//' + self.textbody_tag) + return tbody + # end def find_tbody + + def register (self, transformer) : + """ Registering with a transformer means being able to access + variables stored in the tranformer by other transforms. + + Also needed for tag-computation: The transformer knows which + version of OOo document we are processing. + """ + self.transformer = transformer + mt = self.mimetype = transformer.mimetype + self.textbody_name = self.textbody_names [mt] + self.paragraph_props = self.paragraph_props [mt] + self.properties_tag = self.oootag ('style', self.paragraph_props) + self.textbody_tag = self.oootag ('office', self.textbody_name) + self.font_decls_tag = self.oootag ('office', self.font_decls [mt]) + # end def register + + def oootag (self, namespace, name) : + """ Compute long tag version """ + return OOo_Tag (namespace, name, self.mimetype) + # end def oootag + + def set (self, variable, value) : + """ Set variable in our transformer using naming convention. """ + self.transformer [self._varname (variable)] = value + # end def set + + def _varname (self, name) : + """ For fulfilling the naming convention of the transformer + dictionary (every entry in this dictionary should be prefixed + with the class name of the transform) we have this + convenience method. + Returns variable name prefixed with own class name. + """ + return ":".join ((self.__class__.__name__, name)) + # end def _varname + +# end class Transform + +class Transformer (autosuper) : + """ + Class for applying a set of transforms to a given ooopy object. + The transforms are applied to the specified file in priority + order. When applying transforms we have a mechanism for + communication of transforms. We give the transformer to the + individual transforms as a parameter. The transforms may use the + transformer like a dictionary for storing values and retrieving + values left by previous transforms. + As a naming convention each transform should use its class name + as a prefix for storing values in the dictionary. + >>> import Transforms + >>> from Transforms import renumber_all, get_meta, set_meta, meta_counts + >>> try : + ... from io import StringIO, BytesIO + ... StringIO = BytesIO + ... except ImportError : + ... from StringIO import StringIO + >>> sio = BytesIO () + >>> o = OOoPy (infile = 'testfiles/test.sxw', outfile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> body [-1].get (OOo_Tag ('text', 'style-name', mimetype = m)) + 'Standard' + >>> def cb (name) : + ... r = { 'street' : 'Beispielstrasse 42' + ... , 'firstname' : 'Hugo' + ... , 'salutation' : 'Frau' + ... } + ... if r.has_key (name) : return r [name] + ... return None + ... + >>> p = get_meta (m) + >>> t = Transformer (m, p) + >>> t ['a'] = 'a' + >>> t ['a'] + 'a' + >>> t.transform (o) + >>> p.set ('a', 'b') + >>> t ['Attribute_Access:a'] + 'b' + >>> t = Transformer ( + ... m + ... , Transforms.Autoupdate () + ... , Transforms.Editinfo () + ... , Transforms.Field_Replace (prio = 99, replace = cb) + ... , Transforms.Field_Replace + ... ( replace = + ... { 'salutation' : '' + ... , 'firstname' : 'Erika' + ... , 'lastname' : 'Musterfrau' + ... , 'country' : 'D' + ... , 'postalcode' : '00815' + ... , 'city' : 'Niemandsdorf' + ... } + ... ) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Addpagebreak () + ... ) + >>> t.transform (o) + >>> o.close () + >>> ov = sio.getvalue () + >>> f = open ("testout.sxw", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> c = o.read ('content.xml') + >>> m = o.mimetype + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> vset = './/' + OOo_Tag ('text', 'variable-set', mimetype = m) + >>> for node in body.findall (vset) : + ... name = node.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', node.text + salutation : None + firstname : Erika + lastname : Musterfrau + street : Beispielstrasse 42 + country : D + postalcode : 00815 + city : Niemandsdorf + salutation : None + firstname : Erika + lastname : Musterfrau + street : Beispielstrasse 42 + country : D + postalcode : 00815 + city : Niemandsdorf + >>> body [-1].get (OOo_Tag ('text', 'style-name', mimetype = m)) + 'P2' + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/test.sxw', outfile = sio) + >>> c = o.read ('content.xml') + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Mailmerge + ... ( iterator = + ... ( dict (firstname = 'Erika', lastname = 'Nobody') + ... , dict (firstname = 'Eric', lastname = 'Wizard') + ... , cb + ... ) + ... ) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform (o) + >>> for i in meta_counts : + ... print i, t [':'.join (('Set_Attribute', i))] + character-count 951 + image-count 0 + object-count 0 + page-count 3 + paragraph-count 113 + table-count 3 + word-count 162 + >>> name = t ['Addpagebreak_Style:stylename'] + >>> name + 'P2' + >>> o.close () + >>> ov = sio.getvalue () + >>> f = open ("testout2.sxw", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', m)) + >>> for n in body.findall ('.//*') : + ... zidx = n.get (OOo_Tag ('draw', 'z-index', m)) + ... if zidx : + ... print ':'.join(split_tag (n.tag)), zidx + draw:text-box 0 + draw:rect 1 + draw:text-box 3 + draw:rect 4 + draw:text-box 6 + draw:rect 7 + draw:text-box 2 + draw:text-box 5 + draw:text-box 8 + >>> for n in body.findall ('.//' + OOo_Tag ('text', 'p', m)) : + ... if n.get (OOo_Tag ('text', 'style-name', m)) == name : + ... print n.tag + {http://openoffice.org/2000/text}p + {http://openoffice.org/2000/text}p + >>> vset = './/' + OOo_Tag ('text', 'variable-set', m) + >>> for n in body.findall (vset) : + ... if n.get (OOo_Tag ('text', 'name', m), None).endswith ('name') : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', n.text + firstname : Erika + lastname : Nobody + firstname : Eric + lastname : Wizard + firstname : Hugo + lastname : Testman + firstname : Erika + lastname : Nobody + firstname : Eric + lastname : Wizard + firstname : Hugo + lastname : Testman + >>> for n in body.findall ('.//' + OOo_Tag ('draw', 'text-box', m)) : + ... print n.get (OOo_Tag ('draw', 'name', m)), + ... print n.get (OOo_Tag ('text', 'anchor-page-number', m)) + Frame1 1 + Frame2 2 + Frame3 3 + Frame4 None + Frame5 None + Frame6 None + >>> for n in body.findall ('.//' + OOo_Tag ('text', 'section', m)) : + ... print n.get (OOo_Tag ('text', 'name', m)) + Section1 + Section2 + Section3 + Section4 + Section5 + Section6 + Section7 + Section8 + Section9 + Section10 + Section11 + Section12 + Section13 + Section14 + Section15 + Section16 + Section17 + Section18 + >>> for n in body.findall ('.//' + OOo_Tag ('table', 'table', m)) : + ... print n.get (OOo_Tag ('table', 'name', m)) + Table1 + Table2 + Table3 + >>> r = o.read ('meta.xml') + >>> meta = r.find ('.//' + OOo_Tag ('meta', 'document-statistic', m)) + >>> for i in meta_counts : + ... print i, repr (meta.get (OOo_Tag ('meta', i, m))) + character-count '951' + image-count '0' + object-count '0' + page-count '3' + paragraph-count '113' + table-count '3' + word-count '162' + >>> o.close () + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/test.sxw', outfile = sio) + >>> tf = ('testfiles/test.sxw', 'testfiles/rechng.sxw') + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Concatenate (*tf) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform (o) + >>> for i in meta_counts : + ... print i, repr (t [':'.join (('Set_Attribute', i))]) + character-count '1131' + image-count '0' + object-count '0' + page-count '3' + paragraph-count '168' + table-count '2' + word-count '160' + >>> o.close () + >>> ov = sio.getvalue () + >>> f = open ("testout3.sxw", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> s = o.read ('styles.xml') + >>> for n in c.findall ('./*/*') : + ... name = n.get (OOo_Tag ('style', 'name', m)) + ... if name : + ... parent = n.get (OOo_Tag ('style', 'parent-style-name', m)) + ... print '"%s", "%s"' % (name, parent) + "Tahoma1", "None" + "Bitstream Vera Sans", "None" + "Tahoma", "None" + "Nimbus Roman No9 L", "None" + "Courier New", "None" + "Arial Black", "None" + "New Century Schoolbook", "None" + "Helvetica", "None" + "Table1", "None" + "Table1.A", "None" + "Table1.A1", "None" + "Table1.E1", "None" + "Table1.A2", "None" + "Table1.E2", "None" + "P1", "None" + "fr1", "Frame" + "fr2", "None" + "fr3", "Frame" + "Sect1", "None" + "gr1", "None" + "P2", "Standard" + "Standard_Concat", "None" + "Concat_P1", "Concat_Frame contents" + "Concat_P2", "Concat_Frame contents" + "P3", "Concat_Frame contents" + "P4", "Concat_Frame contents" + "P5", "Concat_Standard" + "P6", "Concat_Standard" + "P7", "Concat_Frame contents" + "P8", "Concat_Frame contents" + "P9", "Concat_Frame contents" + "P10", "Concat_Frame contents" + "P11", "Concat_Frame contents" + "P12", "Concat_Frame contents" + "P13", "Concat_Frame contents" + "P15", "Concat_Standard" + "P16", "Concat_Standard" + "P17", "Concat_Standard" + "P18", "Concat_Standard" + "P19", "Concat_Standard" + "P20", "Concat_Standard" + "P21", "Concat_Standard" + "P22", "Concat_Standard" + "P23", "Concat_Standard" + "T1", "None" + "Concat_fr1", "Concat_Frame" + "Concat_fr2", "Concat_Frame" + "Concat_fr3", "Concat_Frame" + "fr4", "Concat_Frame" + "fr5", "Concat_Frame" + "fr6", "Concat_Frame" + "Concat_Sect1", "None" + "N0", "None" + "N2", "None" + "P15_Concat", "Concat_Standard" + >>> for n in s.findall ('./*/*') : + ... name = n.get (OOo_Tag ('style', 'name', m)) + ... if name : + ... parent = n.get (OOo_Tag ('style', 'parent-style-name', m)) + ... print '"%s", "%s"' % (name, parent) + "Tahoma1", "None" + "Bitstream Vera Sans", "None" + "Tahoma", "None" + "Nimbus Roman No9 L", "None" + "Courier New", "None" + "Arial Black", "None" + "New Century Schoolbook", "None" + "Helvetica", "None" + "Standard", "None" + "Text body", "Standard" + "List", "Text body" + "Table Contents", "Text body" + "Table Heading", "Table Contents" + "Caption", "Standard" + "Frame contents", "Text body" + "Index", "Standard" + "Frame", "None" + "OLE", "None" + "Concat_Standard", "None" + "Concat_Text body", "Concat_Standard" + "Concat_List", "Concat_Text body" + "Concat_Caption", "Concat_Standard" + "Concat_Frame contents", "Concat_Text body" + "Concat_Index", "Concat_Standard" + "Horizontal Line", "Concat_Standard" + "Internet link", "None" + "Visited Internet Link", "None" + "Concat_Frame", "None" + "Concat_OLE", "None" + "pm1", "None" + "Concat_pm1", "None" + "Standard", "None" + "Concat_Standard", "None" + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'variable-decl', m)) : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name + salutation + firstname + lastname + street + country + postalcode + city + date + invoice.invoice_no + invoice.abo.aboprice.abotype.description + address.salutation + address.title + address.firstname + address.lastname + address.function + address.street + address.country + address.postalcode + address.city + invoice.subscriber.salutation + invoice.subscriber.title + invoice.subscriber.firstname + invoice.subscriber.lastname + invoice.subscriber.function + invoice.subscriber.street + invoice.subscriber.country + invoice.subscriber.postalcode + invoice.subscriber.city + invoice.period_start + invoice.period_end + invoice.currency.name + invoice.amount + invoice.subscriber.initial + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'sequence-decl', m)) : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name + Illustration + Table + Text + Drawing + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'p', m)) : + ... name = n.get (OOo_Tag ('text', 'style-name', m)) + ... if not name or name.startswith ('Concat') : + ... print ">%s<" % name + >Concat_P1< + >Concat_P2< + >Concat_Frame contents< + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'text-box', m)) : + ... attrs = 'name', 'style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... attrs.append (n.get (OOo_Tag ('text', 'anchor-page-number', m))) + ... print attrs + ['Frame1', 'fr1', '0', '1'] + ['Frame2', 'fr1', '3', '2'] + ['Frame3', 'Concat_fr1', '6', '3'] + ['Frame4', 'Concat_fr2', '7', '3'] + ['Frame5', 'Concat_fr3', '8', '3'] + ['Frame6', 'Concat_fr1', '9', '3'] + ['Frame7', 'fr4', '10', '3'] + ['Frame8', 'fr4', '11', '3'] + ['Frame9', 'fr4', '12', '3'] + ['Frame10', 'fr4', '13', '3'] + ['Frame11', 'fr4', '14', '3'] + ['Frame12', 'fr4', '15', '3'] + ['Frame13', 'fr5', '16', '3'] + ['Frame14', 'fr4', '18', '3'] + ['Frame15', 'fr4', '19', '3'] + ['Frame16', 'fr4', '20', '3'] + ['Frame17', 'fr6', '17', '3'] + ['Frame18', 'fr4', '23', '3'] + ['Frame19', 'fr3', '2', None] + ['Frame20', 'fr3', '5', None] + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'section', m)) : + ... attrs = 'name', 'style-name' + ... attrs = [n.get (OOo_Tag ('text', i, m)) for i in attrs] + ... print attrs + ['Section1', 'Sect1'] + ['Section2', 'Sect1'] + ['Section3', 'Sect1'] + ['Section4', 'Sect1'] + ['Section5', 'Sect1'] + ['Section6', 'Sect1'] + ['Section7', 'Concat_Sect1'] + ['Section8', 'Concat_Sect1'] + ['Section9', 'Concat_Sect1'] + ['Section10', 'Concat_Sect1'] + ['Section11', 'Concat_Sect1'] + ['Section12', 'Concat_Sect1'] + ['Section13', 'Concat_Sect1'] + ['Section14', 'Concat_Sect1'] + ['Section15', 'Concat_Sect1'] + ['Section16', 'Concat_Sect1'] + ['Section17', 'Concat_Sect1'] + ['Section18', 'Concat_Sect1'] + ['Section19', 'Concat_Sect1'] + ['Section20', 'Concat_Sect1'] + ['Section21', 'Concat_Sect1'] + ['Section22', 'Concat_Sect1'] + ['Section23', 'Concat_Sect1'] + ['Section24', 'Concat_Sect1'] + ['Section25', 'Concat_Sect1'] + ['Section26', 'Concat_Sect1'] + ['Section27', 'Concat_Sect1'] + ['Section28', 'Sect1'] + ['Section29', 'Sect1'] + ['Section30', 'Sect1'] + ['Section31', 'Sect1'] + ['Section32', 'Sect1'] + ['Section33', 'Sect1'] + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'rect', m)) : + ... attrs = 'style-name', 'text-style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... attrs.append (n.get (OOo_Tag ('text', 'anchor-page-number', m))) + ... print attrs + ['gr1', 'P1', '1', '1'] + ['gr1', 'P1', '4', '2'] + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'line', m)) : + ... attrs = 'style-name', 'text-style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... print attrs + ['gr1', 'P1', '24'] + ['gr1', 'P1', '22'] + ['gr1', 'P1', '21'] + >>> for n in s.findall ('.//' + OOo_Tag ('style', 'style', m)) : + ... if n.get (OOo_Tag ('style', 'name', m)).startswith ('Co') : + ... attrs = 'name', 'class', 'family' + ... attrs = [n.get (OOo_Tag ('style', i, m)) for i in attrs] + ... print attrs + ... props = n.find ('./' + OOo_Tag ('style', 'properties', m)) + ... if props is not None and len (props) : + ... props [0].tag + ['Concat_Standard', 'text', 'paragraph'] + '{http://openoffice.org/2000/style}tab-stops' + ['Concat_Text body', 'text', 'paragraph'] + ['Concat_List', 'list', 'paragraph'] + ['Concat_Caption', 'extra', 'paragraph'] + ['Concat_Frame contents', 'extra', 'paragraph'] + ['Concat_Index', 'index', 'paragraph'] + ['Concat_Frame', None, 'graphics'] + ['Concat_OLE', None, 'graphics'] + >>> for n in c.findall ('.//*') : + ... zidx = n.get (OOo_Tag ('draw', 'z-index', m)) + ... if zidx : + ... print ':'.join(split_tag (n.tag)), zidx + draw:text-box 0 + draw:rect 1 + draw:text-box 3 + draw:rect 4 + draw:text-box 6 + draw:text-box 7 + draw:text-box 8 + draw:text-box 9 + draw:text-box 10 + draw:text-box 11 + draw:text-box 12 + draw:text-box 13 + draw:text-box 14 + draw:text-box 15 + draw:text-box 16 + draw:text-box 18 + draw:text-box 19 + draw:text-box 20 + draw:text-box 17 + draw:text-box 23 + draw:line 24 + draw:text-box 2 + draw:text-box 5 + draw:line 22 + draw:line 21 + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/carta.stw', outfile = sio) + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Mailmerge + ... ( iterator = + ... ( dict + ... ( Spett = "Spettabile" + ... , contraente = "First person" + ... , indirizzo = "street? 1" + ... , tipo = "racc. A.C." + ... , luogo = "Varese" + ... , oggetto = "Saluti" + ... ) + ... , dict + ... ( Spett = "Egregio" + ... , contraente = "Second Person" + ... , indirizzo = "street? 2" + ... , tipo = "Raccomandata" + ... , luogo = "Gavirate" + ... , oggetto = "Ossequi" + ... ) + ... ) + ... ) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform(o) + >>> o.close() + >>> ov = sio.getvalue () + >>> f = open ("carta-out.stw", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> vset = './/' + OOo_Tag ('text', 'variable-set', mimetype = m) + >>> for node in body.findall (vset) : + ... name = node.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', node.text + Spett : Spettabile + contraente : First person + indirizzo : street? 1 + Spett : Egregio + contraente : Second Person + indirizzo : street? 2 + tipo : racc. A.C. + luogo : Varese + oggetto : Saluti + tipo : Raccomandata + luogo : Gavirate + oggetto : Ossequi + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/test.odt', outfile = sio) + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Mailmerge + ... ( iterator = + ... ( dict (firstname = 'Erika', lastname = 'Nobody') + ... , dict (firstname = 'Eric', lastname = 'Wizard') + ... , cb + ... ) + ... ) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform (o) + >>> for i in meta_counts : + ... print i, t [':'.join (('Set_Attribute', i))] + character-count 951 + image-count 0 + object-count 0 + page-count 3 + paragraph-count 53 + table-count 3 + word-count 162 + >>> name = t ['Addpagebreak_Style:stylename'] + >>> name + 'P2' + >>> o.close () + >>> ov = sio.getvalue () + >>> f = open ("testout.odt", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', m)) + >>> for n in body.findall ('.//*') : + ... zidx = n.get (OOo_Tag ('draw', 'z-index', m)) + ... if zidx : + ... print ':'.join(split_tag (n.tag)), zidx + draw:frame 0 + draw:rect 1 + draw:frame 3 + draw:rect 4 + draw:frame 6 + draw:rect 7 + draw:frame 2 + draw:frame 5 + draw:frame 8 + >>> for n in body.findall ('.//' + OOo_Tag ('text', 'p', m)) : + ... if n.get (OOo_Tag ('text', 'style-name', m)) == name : + ... print n.tag + {urn:oasis:names:tc:opendocument:xmlns:text:1.0}p + {urn:oasis:names:tc:opendocument:xmlns:text:1.0}p + >>> vset = './/' + OOo_Tag ('text', 'variable-set', m) + >>> for n in body.findall (vset) : + ... if n.get (OOo_Tag ('text', 'name', m), None).endswith ('name') : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', n.text + firstname : Erika + lastname : Nobody + firstname : Eric + lastname : Wizard + firstname : Hugo + lastname : Testman + firstname : Erika + lastname : Nobody + firstname : Eric + lastname : Wizard + firstname : Hugo + lastname : Testman + >>> for n in body.findall ('.//' + OOo_Tag ('draw', 'frame', m)) : + ... print n.get (OOo_Tag ('draw', 'name', m)), + ... print n.get (OOo_Tag ('text', 'anchor-page-number', m)) + Frame1 1 + Frame2 2 + Frame3 3 + Frame4 None + Frame5 None + Frame6 None + >>> for n in body.findall ('.//' + OOo_Tag ('text', 'section', m)) : + ... print n.get (OOo_Tag ('text', 'name', m)) + Section1 + Section2 + Section3 + Section4 + Section5 + Section6 + Section7 + Section8 + Section9 + Section10 + Section11 + Section12 + Section13 + Section14 + Section15 + Section16 + Section17 + Section18 + >>> for n in body.findall ('.//' + OOo_Tag ('table', 'table', m)) : + ... print n.get (OOo_Tag ('table', 'name', m)) + Table1 + Table2 + Table3 + >>> r = o.read ('meta.xml') + >>> meta = r.find ('.//' + OOo_Tag ('meta', 'document-statistic', m)) + >>> for i in meta_counts : + ... print i, repr (meta.get (OOo_Tag ('meta', i, m))) + character-count '951' + image-count '0' + object-count '0' + page-count '3' + paragraph-count '53' + table-count '3' + word-count '162' + >>> o.close () + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/carta.odt', outfile = sio) + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Mailmerge + ... ( iterator = + ... ( dict + ... ( Spett = "Spettabile" + ... , contraente = "First person" + ... , indirizzo = "street? 1" + ... , tipo = "racc. A.C." + ... , luogo = "Varese" + ... , oggetto = "Saluti" + ... ) + ... , dict + ... ( Spett = "Egregio" + ... , contraente = "Second Person" + ... , indirizzo = "street? 2" + ... , tipo = "Raccomandata" + ... , luogo = "Gavirate" + ... , oggetto = "Ossequi" + ... ) + ... ) + ... ) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform(o) + >>> o.close() + >>> ov = sio.getvalue () + >>> f = open ("carta-out.odt", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> vset = './/' + OOo_Tag ('text', 'variable-set', mimetype = m) + >>> for node in body.findall (vset) : + ... name = node.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', node.text + Spett : Spettabile + contraente : First person + indirizzo : street? 1 + Spett : Egregio + contraente : Second Person + indirizzo : street? 2 + tipo : racc. A.C. + luogo : Varese + oggetto : Saluti + tipo : Raccomandata + luogo : Gavirate + oggetto : Ossequi + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/test.odt', outfile = sio) + >>> tf = ('testfiles/test.odt', 'testfiles/rechng.odt') + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Concatenate (*tf) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform (o) + >>> for i in meta_counts : + ... print i, repr (t [':'.join (('Set_Attribute', i))]) + character-count '1131' + image-count '0' + object-count '0' + page-count '3' + paragraph-count '80' + table-count '2' + word-count '159' + >>> o.close () + >>> ov = sio.getvalue () + >>> f = open ("testout3.odt", "wb") + >>> f.write (ov) + >>> f.close () + >>> o = OOoPy (infile = sio) + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> s = o.read ('styles.xml') + >>> for n in c.findall ('./*/*') : + ... name = n.get (OOo_Tag ('style', 'name', m)) + ... if name : + ... parent = n.get (OOo_Tag ('style', 'parent-style-name', m)) + ... print '"%s", "%s"' % (name, parent) + "Tahoma1", "None" + "Bitstream Vera Sans", "None" + "Tahoma", "None" + "Nimbus Roman No9 L", "None" + "Courier New", "None" + "Arial Black", "None" + "New Century Schoolbook", "None" + "Times New Roman", "None" + "Arial", "None" + "Helvetica", "None" + "Table1", "None" + "Table1.A", "None" + "Table1.A1", "None" + "Table1.E1", "None" + "Table1.A2", "None" + "Table1.E2", "None" + "P1", "None" + "fr1", "Frame" + "fr2", "Frame" + "Sect1", "None" + "gr1", "None" + "P2", "Standard" + "Standard_Concat", "None" + "Concat_P1", "Concat_Frame_20_contents" + "Concat_P2", "Concat_Frame_20_contents" + "P3", "Concat_Frame_20_contents" + "P4", "Concat_Standard" + "P5", "Concat_Standard" + "P6", "Concat_Frame_20_contents" + "P7", "Concat_Frame_20_contents" + "P8", "Concat_Frame_20_contents" + "P9", "Concat_Frame_20_contents" + "P10", "Concat_Frame_20_contents" + "P11", "Concat_Frame_20_contents" + "P12", "Concat_Frame_20_contents" + "P14", "Concat_Standard" + "P15", "Concat_Standard" + "P16", "Concat_Standard" + "P17", "Concat_Standard" + "P18", "Concat_Standard" + "P19", "Concat_Standard" + "P20", "Concat_Standard" + "P21", "Concat_Standard" + "P22", "Concat_Standard" + "P23", "Concat_Standard" + "Concat_fr1", "Frame" + "Concat_fr2", "Frame" + "fr3", "Frame" + "fr4", "Frame" + "fr5", "Frame" + "fr6", "Frame" + "Concat_gr1", "None" + "N0", "None" + "N2", "None" + "P14_Concat", "Concat_Standard" + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'variable-decl', m)) : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name + salutation + firstname + lastname + street + country + postalcode + city + date + invoice.invoice_no + invoice.abo.aboprice.abotype.description + address.salutation + address.title + address.firstname + address.lastname + address.function + address.street + address.country + address.postalcode + address.city + invoice.subscriber.salutation + invoice.subscriber.title + invoice.subscriber.firstname + invoice.subscriber.lastname + invoice.subscriber.function + invoice.subscriber.street + invoice.subscriber.country + invoice.subscriber.postalcode + invoice.subscriber.city + invoice.period_start + invoice.period_end + invoice.currency.name + invoice.amount + invoice.subscriber.initial + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'sequence-decl', m)) : + ... name = n.get (OOo_Tag ('text', 'name', m)) + ... print name + Illustration + Table + Text + Drawing + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'p', m)) : + ... name = n.get (OOo_Tag ('text', 'style-name', m)) + ... if not name or name.startswith ('Concat') : + ... print ':'.join(split_tag (n.tag)), ">%s<" % name + text:p >None< + text:p >None< + text:p >Concat_P1< + text:p >Concat_P1< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_P2< + text:p >Concat_Frame_20_contents< + text:p >None< + text:p >None< + text:p >None< + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'frame', m)) : + ... attrs = 'name', 'style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... attrs.append (n.get (OOo_Tag ('text', 'anchor-page-number', m))) + ... print attrs + ['Frame1', 'fr1', '0', '1'] + ['Frame2', 'fr1', '3', '2'] + ['Frame3', 'Concat_fr1', '6', '3'] + ['Frame4', 'Concat_fr2', '7', '3'] + ['Frame5', 'fr3', '8', '3'] + ['Frame6', 'Concat_fr1', '9', '3'] + ['Frame7', 'fr4', '10', '3'] + ['Frame8', 'fr4', '11', '3'] + ['Frame9', 'fr4', '12', '3'] + ['Frame10', 'fr4', '13', '3'] + ['Frame11', 'fr4', '14', '3'] + ['Frame12', 'fr4', '15', '3'] + ['Frame13', 'fr5', '16', '3'] + ['Frame14', 'fr4', '18', '3'] + ['Frame15', 'fr4', '19', '3'] + ['Frame16', 'fr4', '20', '3'] + ['Frame17', 'fr6', '17', '3'] + ['Frame18', 'fr4', '23', '3'] + ['Frame19', 'fr2', '2', None] + ['Frame20', 'fr2', '5', None] + >>> for n in c.findall ('.//' + OOo_Tag ('text', 'section', m)) : + ... attrs = 'name', 'style-name' + ... attrs = [n.get (OOo_Tag ('text', i, m)) for i in attrs] + ... print attrs + ['Section1', 'Sect1'] + ['Section2', 'Sect1'] + ['Section3', 'Sect1'] + ['Section4', 'Sect1'] + ['Section5', 'Sect1'] + ['Section6', 'Sect1'] + ['Section7', 'Sect1'] + ['Section8', 'Sect1'] + ['Section9', 'Sect1'] + ['Section10', 'Sect1'] + ['Section11', 'Sect1'] + ['Section12', 'Sect1'] + ['Section13', 'Sect1'] + ['Section14', 'Sect1'] + ['Section15', 'Sect1'] + ['Section16', 'Sect1'] + ['Section17', 'Sect1'] + ['Section18', 'Sect1'] + ['Section19', 'Sect1'] + ['Section20', 'Sect1'] + ['Section21', 'Sect1'] + ['Section22', 'Sect1'] + ['Section23', 'Sect1'] + ['Section24', 'Sect1'] + ['Section25', 'Sect1'] + ['Section26', 'Sect1'] + ['Section27', 'Sect1'] + ['Section28', 'Sect1'] + ['Section29', 'Sect1'] + ['Section30', 'Sect1'] + ['Section31', 'Sect1'] + ['Section32', 'Sect1'] + ['Section33', 'Sect1'] + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'rect', m)) : + ... attrs = 'style-name', 'text-style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... attrs.append (n.get (OOo_Tag ('text', 'anchor-page-number', m))) + ... print attrs + ['gr1', 'P1', '1', '1'] + ['gr1', 'P1', '4', '2'] + >>> for n in c.findall ('.//' + OOo_Tag ('draw', 'line', m)) : + ... attrs = 'style-name', 'text-style-name', 'z-index' + ... attrs = [n.get (OOo_Tag ('draw', i, m)) for i in attrs] + ... print attrs + ['Concat_gr1', 'P1', '24'] + ['Concat_gr1', 'P1', '22'] + ['Concat_gr1', 'P1', '21'] + >>> for n in s.findall ('.//' + OOo_Tag ('style', 'style', m)) : + ... if n.get (OOo_Tag ('style', 'name', m)).startswith ('Co') : + ... attrs = 'name', 'display-name', 'class', 'family' + ... attrs = [n.get (OOo_Tag ('style', i, m)) for i in attrs] + ... print attrs + ... props = n.find ('./' + OOo_Tag ('style', 'properties', m)) + ... if props is not None and len (props) : + ... props [0].tag + ['Concat_Standard', None, 'text', 'paragraph'] + ['Concat_Text_20_body', 'Concat Text body', 'text', 'paragraph'] + ['Concat_List', None, 'list', 'paragraph'] + ['Concat_Caption', None, 'extra', 'paragraph'] + ['Concat_Frame_20_contents', 'Concat Frame contents', 'extra', 'paragraph'] + ['Concat_Index', None, 'index', 'paragraph'] + >>> for n in c.findall ('.//*') : + ... zidx = n.get (OOo_Tag ('draw', 'z-index', m)) + ... if zidx : + ... print ':'.join(split_tag (n.tag)), zidx + draw:frame 0 + draw:rect 1 + draw:frame 3 + draw:rect 4 + draw:frame 6 + draw:frame 7 + draw:frame 8 + draw:frame 9 + draw:frame 10 + draw:frame 11 + draw:frame 12 + draw:frame 13 + draw:frame 14 + draw:frame 15 + draw:frame 16 + draw:frame 18 + draw:frame 19 + draw:frame 20 + draw:frame 17 + draw:frame 23 + draw:line 24 + draw:frame 2 + draw:frame 5 + draw:line 22 + draw:line 21 + >>> from os import system + >>> system ('python bin/ooo_fieldreplace -i testfiles/test.odt ' + ... '-o testout.odt ' + ... 'salutation=Frau firstname=Erika lastname=Musterfrau ' + ... 'country=D postalcode=00815 city=Niemandsdorf ' + ... 'street="Beispielstrasse 42"') + 0 + >>> o = OOoPy (infile = 'testout.odt') + >>> c = o.read ('content.xml') + >>> m = o.mimetype + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> vset = './/' + OOo_Tag ('text', 'variable-set', mimetype = m) + >>> for node in body.findall (vset) : + ... name = node.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', node.text + salutation : Frau + firstname : Erika + lastname : Musterfrau + street : Beispielstrasse 42 + country : D + postalcode : 00815 + city : Niemandsdorf + salutation : Frau + firstname : Erika + lastname : Musterfrau + street : Beispielstrasse 42 + country : D + postalcode : 00815 + city : Niemandsdorf + >>> o.close () + >>> system ("bin/ooo_mailmerge -o testout.odt -d'|' " + ... "testfiles/carta.odt testfiles/x.csv") + 0 + >>> o = OOoPy (infile = 'testout.odt') + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> vset = './/' + OOo_Tag ('text', 'variable-set', mimetype = m) + >>> for node in body.findall (vset) : + ... name = node.get (OOo_Tag ('text', 'name', m)) + ... print name, ':', node.text + Spett : Spettabile + contraente : First person + indirizzo : street? 1 + Spett : Egregio + contraente : Second Person + indirizzo : street? 2 + tipo : racc. A.C. + luogo : Varese + oggetto : Saluti + tipo : Raccomandata + luogo : Gavirate + oggetto : Ossequi + >>> o.close () + >>> infile = 'testfiles/testenum.odt' + >>> o = OOoPy (infile = infile, outfile = 'xyzzy.odt') + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Addpagebreak_Style () + ... , Transforms.Mailmerge + ... ( iterator = + ... ( dict (firstname = 'Erika', lastname = 'Nobody') + ... , dict (firstname = 'Eric', lastname = 'Wizard') + ... , cb + ... ) + ... ) + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... ) + >>> t.transform (o) + >>> o.close () + >>> o = OOoPy (infile = 'xyzzy.odt') + >>> m = o.mimetype + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> textlist = './/' + OOo_Tag ('text', 'list', m) + >>> for node in body.findall (textlist) : + ... id = node.get (OOo_Tag ('xml', 'id', m)) + ... print 'xml:id', ':', id + xml:id : list1 + xml:id : list2 + xml:id : list3 + >>> o = OOoPy (infile = 'testfiles/page1.odt', outfile = 'xyzzy.odt') + >>> m = o.mimetype + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Concatenate ('testfiles/page2.odt') + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... , Transforms.Manifest_Append () + ... ) + >>> t.transform (o) + >>> o.close () + >>> o = OOoPy (infile = 'xyzzy.odt') + >>> c = o.read ('META-INF/manifest.xml') + >>> for node in c.getroot () : + ... fe = node.get (OOo_Tag ('manifest', 'full-path', m)) + ... print fe + / + Pictures/10000000000000C80000007941B1A419.jpg + Pictures/10000000000000DC000000B02E191635.jpg + Pictures/10000000000000DC000000A337377AAA.jpg + meta.xml + settings.xml + content.xml + Thumbnails/thumbnail.png + layout-cache + manifest.rdf + Configurations2/accelerator/current.xml + Configurations2/ + styles.xml + >>> for f in o.izip.infolist () : + ... print f.filename + mimetype + settings.xml + META-INF/manifest.xml + content.xml + meta.xml + styles.xml + Pictures/10000000000000C80000007941B1A419.jpg + Pictures/10000000000000DC000000B02E191635.jpg + Pictures/10000000000000DC000000A337377AAA.jpg + Thumbnails/thumbnail.png + layout-cache + manifest.rdf + Configurations2/images/Bitmaps/ + Configurations2/accelerator/current.xml + >>> sio = StringIO () + >>> o = OOoPy (infile = 'testfiles/tbl_first.odt', outfile = sio) + >>> m = o.mimetype + >>> t = Transformer ( + ... o.mimetype + ... , get_meta (o.mimetype) + ... , Transforms.Concatenate ('testfiles/tbl_second.odt') + ... , renumber_all (o.mimetype) + ... , set_meta (o.mimetype) + ... , Transforms.Fix_OOo_Tag () + ... , Transforms.Manifest_Append () + ... ) + >>> t.transform (o) + >>> o.close () + >>> o = OOoPy (infile = sio) + >>> c = o.read ('content.xml') + >>> body = c.find (OOo_Tag ('office', 'body', mimetype = m)) + >>> tbls = './/' + OOo_Tag ('table', 'table', mimetype = m) + >>> for table in body.findall (tbls) : + ... name = table.get (OOo_Tag ('table', 'style-name', mimetype = m)) + ... if name : + ... print name + ... for t in table.findall ('.//') : + ... name = t.get (OOo_Tag ('table', 'style-name', mimetype = m)) + ... if name : + ... print name + Tabella1 + Tabella1.A + Tabella1.A1 + Tabella1.B1 + Tabella1.A2 + Tabella1.B2 + Tabella1 + Tabella1.A + Tabella1.A1 + Tabella1.B1 + Tabella1.A2 + Tabella1.B2 + """ + + def __init__ (self, mimetype, *tf) : + assert (mimetype in mimetypes) + self.mimetype = mimetype + self.transforms = {} + for t in tf : + self.insert (t) + self.dictionary = {} + self.has_key = self.dictionary.has_key + self.__contains__ = self.has_key + # 2-tuples of filename, content + self.appendfiles = [] + # end def __init__ + + def insert (self, transform) : + """Insert a new transform""" + t = transform + if t.prio not in self.transforms : + self.transforms [t.prio] = [] + self.transforms [t.prio].append (t) + t.register (self) + # end def append + + def transform (self, ooopy) : + """ + Apply all the transforms in priority order. + Priority order is global over all transforms. + """ + self.trees = {} + for f in files : + self.trees [f] = ooopy.read (f) + #self.dictionary = {} # clear dict when transforming another ooopy + prios = self.transforms.keys () + prios.sort () + for p in prios : + for t in self.transforms [p] : + t.apply_all (self.trees) + for e in self.trees.itervalues () : + e.write () + for fname, fcontent in self.appendfiles : + e.ooopy.append_file (fname, fcontent) + # end def transform + + def __getitem__ (self, key) : + return self.dictionary [key] + # end def __getitem__ + + def __setitem__ (self, key, value) : + self.dictionary [key] = value + # end def __setitem__ +# end class Transformer diff --git a/OOoPy-1.11/ooopy/Transforms.py b/OOoPy-1.11/ooopy/Transforms.py new file mode 100644 index 0000000..50a6c0d --- /dev/null +++ b/OOoPy-1.11/ooopy/Transforms.py @@ -0,0 +1,1237 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2005-14 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +from __future__ import absolute_import + +import time +import re +try : + from xml.etree.ElementTree import dump, SubElement, Element, tostring +except ImportError : + from elementtree.ElementTree import dump, SubElement, Element, tostring +from copy import deepcopy +from ooopy.OOoPy import OOoPy, autosuper +from ooopy.Transformer import files, split_tag, OOo_Tag, Transform +from ooopy.Transformer import mimetypes, namespace_by_name +from ooopy.Version import VERSION + +# counts in meta.xml +meta_counts = \ + ( 'character-count', 'image-count', 'object-count', 'page-count' + , 'paragraph-count', 'table-count', 'word-count' + ) + +class Access_Attribute (autosuper) : + """ For performance reasons we do not specify a separate transform + for each attribute-read or -change operation. Instead we define + all the attribute accesses we want to perform as objects that + follow the attribute access api and apply them all using an + Attribute_Access in one go. + """ + + def __init__ (self, key = None, prefix = None, ** kw) : + self.__super.__init__ (key = key, prefix = prefix, **kw) + self.key = key + if key : + if not prefix : + prefix = self.__class__.__name__ + self.key = ':'.join ((prefix, key)) + # end def __init__ + + def register (self, transformer) : + self.transformer = transformer + # end def register + + def use_value (self, oldval = None) : + """ Can change the given value by returning the new value. If + returning None or oldval the attribute stays unchanged. + """ + raise NotImplementedError, "use_value must be defined in derived class" + # end def use_value + +# end class Access_Attribute + +class Get_Attribute (Access_Attribute) : + """ An example of not changing an attribute but only storing the + value in the transformer + """ + + def __init__ (self, tag, attr, key, transform = None, ** kw) : + self.__super.__init__ (key = key, **kw) + self.tag = tag + self.attribute = attr + self.transform = transform + # end def __init__ + + def use_value (self, oldval = None) : + self.transformer [self.key] = oldval + return None + # end def use_value + +# end def Get_Attribute + +class Get_Max (Access_Attribute) : + """ Get the maximum value of an attribute """ + + def __init__ (self, tag, attr, key, transform = None, ** kw) : + self.__super.__init__ (key = key, **kw) + self.tag = tag + self.attribute = attr + self.transform = transform + # end def __init__ + + def register (self, transformer) : + self.__super.register (transformer) + self.transformer [self.key] = -1 + # end def register + + def use_value (self, oldval = None) : + if self.transformer [self.key] < oldval : + self.transformer [self.key] = oldval + return None + # end def use_value + +# end def Get_Max + +class Renumber (Access_Attribute) : + """ Specifies a renumbering transform. OOo has a 'name' attribute + for several different tags, e.g., tables, frames, sections etc. + These names must be unique in the whole document. OOo itself + solves this by appending a unique number to a basename for each + element, e.g., sections are named 'Section1', 'Section2', ... + Renumber transforms can be applied to correct the numbering + after operations that destroy the unique numbering, e.g., after + a mailmerge where the same document is repeatedly appended. + + The force parameter specifies if the new renumbered name should + be inserted even if the attribute in question does not exist. + """ + + def __init__ \ + (self, tag, name = None, attr = None, start = 1, force = False) : + self.__super.__init__ () + tag_ns, tag_name = split_tag (tag) + self.tag_ns = tag_ns + self.tag = tag + self.name = name or tag_name [0].upper () + tag_name [1:] + self.num = start + self.force = force + self.attribute = attr + # end def __init__ + + def register (self, transformer) : + self.__super.register (transformer) + if not self.attribute : + self.attribute = OOo_Tag (self.tag_ns, 'name', transformer.mimetype) + # end def register + + def use_value (self, oldval = None) : + if oldval is None and not self.force : + return + name = "%s%d" % (self.name, self.num) + self.num += 1 + return name + # end def use_value + +# end class Renumber + +class Set_Attribute (Access_Attribute) : + """ + Similar to the renumbering transform in that we are assigning + new values to some attributes. But in this case we give keys + into the Transformer dict to replace some tag attributes. + """ + + def __init__ \ + ( self + , tag + , attr + , key = None + , transform = None + , value = None + , oldvalue = None + , ** kw + ) : + self.__super.__init__ (key = key, ** kw) + self.tag = tag + self.attribute = attr + self.transform = transform + self.value = value + self.oldvalue = oldvalue + # end def __init__ + + def use_value (self, oldval) : + if oldval is None : + return None + if self.oldvalue and oldval != self.oldvalue : + return None + if self.key and self.transformer.has_key (self.key) : + return str (self.transformer [self.key]) + return self.value + # end def use_value + +# end class Set_Attribute + +def set_attributes_from_dict (tag, attr, d) : + """ Convenience function: iterate over a dict and return a list of + Set_Attribute objects specifying replacement of attributes in + the dictionary + """ + return [Set_Attribute (tag, attr, oldvalue = k, value = v) + for k,v in d.iteritems () + ] +# end def set_attributes_from_dict + +class Reanchor (Access_Attribute) : + """ + Similar to the renumbering transform in that we are assigning + new values to some attributes. But in this case we want to + relocate objects that are anchored to a page. + """ + + def __init__ (self, offset, tag, attr = None) : + self.__super.__init__ () + self.offset = int (offset) + self.tag = tag + self.attribute = attr + # end def __init__ + + def register (self, transformer) : + self.__super.register (transformer) + if not self.attribute : + self.attribute = \ + OOo_Tag ('text', 'anchor-page-number', transformer.mimetype) + # end def register + + def use_value (self, oldval) : + if oldval is None : + return oldval + return "%d" % (int (oldval) + self.offset) + # end def use_value + +# end class Reanchor + +# +# general transforms applicable to several .xml files +# + +class Attribute_Access (Transform) : + """ + Read or Change attributes in an OOo document. + Can be used for renumbering, moving anchored objects, etc. + Expects a list of attribute changer objects that follow the + attribute changer API. This API is very simple: + + - Member function "use_value" returns the new value of an + attribute, or if unchanged the old value + - The attribute "tag" gives the tag for an element we are + searching + - The attribute "attribute" gives the name of the attribute we + want to read or change. + For examples of the attribute changer API, see Renumber and + Reanchor above. + """ + filename = 'content.xml' + prio = 110 + + def __init__ (self, attrchangers, filename = None, ** kw) : + self.filename = filename or self.filename + self.attrchangers = {} + # allow several changers for a single tag + self.attrchangers [None] = [] + self.changers = attrchangers + self.__super.__init__ (** kw) + # end def __init__ + + def register (self, transformer) : + """ Register transformer with all attrchangers. """ + self.__super.register (transformer) + for r in self.changers : + if r.tag not in self.attrchangers : + self.attrchangers [r.tag] = [] + self.attrchangers [r.tag].append (r) + r.register (transformer) + # end def register + + def apply (self, root) : + """ Search for all tags for which we renumber and replace name """ + for n in [root] + root.findall ('.//*') : + changers = \ + self.attrchangers [None] + self.attrchangers.get (n.tag, []) + for r in changers : + nval = r.use_value (n.get (r.attribute)) + if nval is not None : + n.set (r.attribute, nval) + # end def apply + +# end class Attribute_Access + +# +# META-INF/manifest.xml transforms +# + +class Manifest_Append (Transform) : + """ + The Transformer stores a list of files (and contents) to append. + These files are added to the archive later but need to be + present in the manifest, too. + The file list in the Transformer currently doesn't store a media + type (which is one of the parameters in the manifest), the + current application of this transform is to add pictures -- + these don't have a media type in the files that were checked. + So for now we add an empty media type. + """ + filename = 'META-INF/manifest.xml' + prio = 1000 + + def apply (self, root) : + for n, node in enumerate (root) : + assert node.tag == self.oootag ('manifest', 'file-entry') + path = node.get (self.oootag ('manifest', 'full-path')) + assert (path) + if path == '/' : + break + else : + assert (not "The manifest needs a '/' entry") + for f, _ in self.transformer.appendfiles : + e = Element (self.oootag ('manifest', 'file-entry')) + e.attrib [self.oootag ('manifest', 'full-path')] = f + e.attrib [self.oootag ('manifest', 'media-type')] = '' + root.insert (n + 1, e) + n += 1 + # end def apply + +# end class Manifest_Append + +# +# meta.xml transforms +# + +class Editinfo (Transform) : + """ + This is an example of modifying OOo meta info (edit information, + author, etc). We set some of the items (program that generated + the OOo file, modification time, number of edit cyles and overall + edit duration). It's easy to subclass this transform and replace + the "replace" variable (pun intended) in the derived class. + """ + filename = 'meta.xml' + prio = 20 + repl = \ + { ('meta', 'generator') : 'OOoPy field replacement' + , ('dc', 'date') : time.strftime ('%Y-%m-%dT%H:%M:%S') + , ('meta', 'editing-cycles') : '0' + , ('meta', 'editing-duration') : 'PT0M0S' + } + replace = {} + # iterate over all mimetypes, so this works for all known mimetypes + # of OOo documents. + for m in mimetypes : + for params, value in repl.iteritems () : + replace [OOo_Tag (mimetype = m, *params)] = value + + def apply (self, root) : + for node in root.findall (self.oootag ('office', 'meta') + '/*') : + if self.replace.has_key (node.tag) : + node.text = self.replace [node.tag] + # end def apply +# end class Editinfo + +# +# settings.xml transforms +# + +class Autoupdate (Transform) : + """ + This is an example of modifying OOo settings. We set some of the + AutoUpdate configuration items in OOo to true. We also specify + that links should be updated when reading. + + This was originally intended to make OOo correctly display fields + if they were changed with the Field_Replace below + (similar to pressing F9 after loading the generated document in + OOo). In particular I usually make spaces depend on field + contents so that I don't have spurious spaces if a field is + empty. Now it would be nice if OOo displayed the spaces correctly + after loading a document (It does update the fields before + printing, so this is only a cosmetic problem :-). This apparently + does not work. If anybody knows how to achieve this, please let + me know: mailto:rsc@runtux.com + """ + filename = 'settings.xml' + prio = 20 + + def apply (self, root) : + config = None + for config in root.findall \ + ( self.oootag ('office', 'settings') + + '/' + + self.oootag ('config', 'config-item-set') + ) : + name = config.get (self.oootag ('config', 'name')) + if name == 'configuration-settings' : + break + for node in config.findall (self.oootag ('config', 'config-item')) : + name = node.get (self.oootag ('config', 'name')) + if name == 'LinkUpdateMode' : # update when reading + node.text = '2' + # update fields when reading + if name == 'FieldAutoUpdate' or name == 'ChartAutoUpdate' : + node.text = 'true' + # end def apply +# end class Autoupdate + +# +# content.xml transforms +# + +class Field_Replace (Transform) : + """ + Takes a dict of replacement key-value pairs. The key is the name + of a variable in OOo. Additional replacement key-value pairs may + be specified in ** kw. Alternatively a callback mechanism for + variable name lookups is provided. The callback function is + given the name of a variable in OOo and is expected to return + the replacement value or None if the variable value should not + be replaced. + """ + filename = 'content.xml' + prio = 100 + + def __init__ (self, prio = None, replace = None, ** kw) : + """ replace is something behaving like a dict or something + callable for name lookups + """ + self.__super.__init__ (prio, ** kw) + self.replace = replace or {} + self.dict = kw + # end def __init__ + + def apply (self, root) : + tbody = self.find_tbody (root) + for tag in 'variable-set', 'variable-get', 'variable-input' : + for node in tbody.findall ('.//' + self.oootag ('text', tag)) : + attr = 'name' + if tag == 'text-input' : + attr = 'description' + name = node.get (self.oootag ('text', attr)) + if callable (self.replace) : + replace = self.replace (name) + if replace : + node.text = replace + elif name in self.replace : + node.text = self.replace [name] + elif name in self.dict : + node.text = self.dict [name] + # end def apply +# end class Field_Replace + +class Addpagebreak_Style (Transform) : + """ + This transformation adds a new ad-hoc paragraph style to the + content part of the OOo document. This is needed to be able to + add new page breaks to an OOo document. Adding a new page break + is then a matter of adding an empty paragraph with the given page + break style. + + We first look through all defined paragraph styles for + determining a new paragraph style number. Convention is P + for paragraph styles. We search the highest number and use this + incremented by one for the new style to insert. Then we insert + the new style and store the resulting style name in the + transformer under the key class_name:stylename where class_name + is our own class name. + """ + filename = 'content.xml' + prio = 30 + para = re.compile (r'P([0-9]+)') + + def apply (self, root) : + max_style = 0 + styles = root.find (self.oootag ('office', 'automatic-styles')) + for s in styles.findall ('./' + self.oootag ('style', 'style')) : + m = self.para.match (s.get (self.oootag ('style', 'name'), '')) + if m : + num = int (m.group (1)) + if num > max_style : + max_style = num + stylename = 'P%d' % (max_style + 1) + new = SubElement \ + ( styles + , self.oootag ('style', 'style') + , { self.oootag ('style', 'name') : stylename + , self.oootag ('style', 'family') : 'paragraph' + , self.oootag ('style', 'parent-style-name') : 'Standard' + } + ) + SubElement \ + ( new + , self.properties_tag + , { self.oootag ('fo', 'break-after') : 'page' } + ) + self.set ('stylename', stylename) + # end def apply +# end class Addpagebreak_Style + +class Addpagebreak (Transform) : + """ + This transformation adds a page break to the last page of the OOo + text. This is needed, e.g., when doing mail-merge: We append a + page break to the tbody and then append the next page. This + transform needs the name of the paragraph style specifying the + page break style. Default is to use + 'Addpagebreak_Style:stylename' as the key for + retrieving the page style. Alternatively the page style or the + page style key can be specified in the constructor. + """ + filename = 'content.xml' + prio = 50 + + def __init__ (self, stylename = None, stylekey = None, ** kw) : + self.__super.__init__ (** kw) + self.stylename = stylename + self.stylekey = stylekey or 'Addpagebreak_Style:stylename' + # end def __init__ + + def apply (self, root) : + """append to tbody e.g., """ + tbody = self.find_tbody (root) + stylename = self.stylename or self.transformer [self.stylekey] + SubElement \ + ( tbody + , self.oootag ('text', 'p') + , { self.oootag ('text', 'style-name') : stylename } + ) + # end def apply +# end class Addpagebreak + +class Fix_OOo_Tag (Transform) : + """ + OOo writer conditions are attributes where the *value* is + prefixed by an XML namespace. If the ooow namespace declaration + is not in scope, all conditions will evaluate to false. I + consider this a bug (a violation of the ideas of XML) of OOo. + Nevertheless to make conditions work, we insert the ooow + namespace declaration into the top-level element. + """ + filename = 'content.xml' + prio = 10000 + + def apply (self, root) : + if self.mimetype == mimetypes [1] : + root.set ('xmlns:ooow', namespace_by_name [self.mimetype]['ooow']) + # end def apply +# end class Fix_OOo_Tag + +class _Body_Concat (Transform) : + """ Various methods for modifying the tbody split into various pieces + that have to keep sequence in order to not confuse OOo. + """ + ooo_sections = {} + for m in mimetypes : + ooo_sections [m] = \ + [ { OOo_Tag ('text', 'variable-decls', m) : 1 + , OOo_Tag ('text', 'sequence-decls', m) : 1 + , OOo_Tag ('text', 'user-field-decls', m) : 1 + , OOo_Tag ('office', 'forms', m) : 1 + } + , { OOo_Tag ('draw', 'frame', m) : 1 + , OOo_Tag ('draw', 'rect', m) : 1 + , OOo_Tag ('draw', 'text-box', m) : 1 + } + ] + + def _textbody (self) : + """ + We use the office:body (OOo 1.X)/office:text (OOo 1.X) + element as a container for various transforms... + """ + return Element (self.textbody_tag) + # end def _textbody + + def _divide (self, textbody) : + """ Divide self.copy into parts that must keep their sequence. + We use another textbody tag for storing the parts... + Side-effect of setting self.copyparts is intended. + """ + self.copyparts = self._textbody () + self.copyparts.append (self._textbody ()) + l = len (self.ooo_sections [self.mimetype]) + idx = 0 + for e in textbody : + while idx < l : + if e.tag in self.ooo_sections [self.mimetype][idx] : + break + else : + self.copyparts.append (self._textbody ()) + idx += 1 + self.copyparts [-1].append (e) + declarations = self.copyparts [0] + del self.copyparts [0] + return declarations + # end def _divide + + def divide_body (self, root) : + cont = root + if cont.tag != self.oootag ('office', 'document-content') : + cont = root.find (self.oootag ('office', 'document-content')) + tbody = cont.find (self.oootag ('office', 'body')) + # OOo 2.X has an office:text inside office:body that contains + # the real text contents: + if self.mimetype == mimetypes [1] : + cont = tbody + tbody = cont.find (self.oootag ('office', 'text')) + idx = cont [:].index (tbody) + self.tbody = cont [idx] = self._textbody () + self.declarations = self._divide (tbody) + self.bodyparts = self.copyparts + # end def divide_body + + def append_declarations (self) : + for e in self.declarations : + self.tbody.append (e) + # end def append_declarations + + def append_to_body (self, cp) : + for i in range (len (self.bodyparts)) : + for j in cp [i] : + self.bodyparts [i].append (j) + # end def append_to_body + + def assemble_body (self) : + for p in self.bodyparts : + for e in p : + self.tbody.append (e) + # end def assemble_body + + def _get_meta (self, var, classname = 'Get_Attribute', prefix = "") : + """ get page- and paragraph-count etc. meta-info """ + return int (self.transformer [':'.join ((classname, prefix + var))]) + # end def _get_meta + + def _set_meta (self, var, value, classname = 'Set_Attribute', prefix = "") : + """ set page- and paragraph-count etc. meta-info """ + self.transformer [':'.join ((classname, prefix + var))] = str (value) + # end def _set_meta +# end class _Body_Concat + +class Mailmerge (_Body_Concat) : + """ + This transformation is used to create a mailmerge document using + the current document as the template. In the constructor we get + an iterator that provides a data set for each item in the + iteration. Elements the iterator has to provide are either + something that follows the Mapping Type interface (it looks like + a dict) or something that is callable and can be used for + name-value lookups. + + A precondition for this transform is the application of the + Addpagebreak_Style to guarantee that we know the style + for adding a page break to the current document. Alternatively + the stylename (or the stylekey if a different name should be used + for lookup in the current transformer) can be given in the + constructor. + """ + filename = 'content.xml' + prio = 60 + + def __init__ \ + (self, iterator, stylename = None, stylekey = None, ** kw) : + self.__super.__init__ (** kw) + self.iterator = iterator + self.stylename = stylename + self.stylekey = stylekey + # end def __init__ + + def apply (self, root) : + """ + Copy old tbody, create new empty one and repeatedly append the + new tbody. + """ + pb = Addpagebreak \ + ( stylename = self.stylename + , stylekey = self.stylekey + , transformer = self.transformer + ) + zi = Attribute_Access \ + ( (Get_Max (None, self.oootag ('draw', 'z-index'), 'z-index'),) + , transformer = self.transformer + ) + zi.apply (root) + + pagecount = self._get_meta ('page-count') + z_index = self._get_meta ('z-index', classname = 'Get_Max') + 1 + ra = Attribute_Access \ + ( ( Reanchor (pagecount, self.oootag ('draw', 'text-box')) + , Reanchor (pagecount, self.oootag ('draw', 'rect')) + , Reanchor (pagecount, self.oootag ('draw', 'frame')) + , Reanchor (z_index, None, self.oootag ('draw', 'z-index')) + ) + , transformer = self.transformer # transformer added + ) + self.divide_body (root) + self.bodyparts = [self._textbody () for i in self.copyparts] + + count = 0 + for i in self.iterator : + count += 1 + fr = Field_Replace (replace = i, transformer = self.transformer) + # add page break only to non-empty tbody + # reanchor only after the first mailmerge + if len (self.tbody) : # tbody non-empty (but existing!) + pb.apply (self.bodyparts [-1]) + ra.apply (self.copyparts) + else : + self.append_declarations () + cp = deepcopy (self.copyparts) + fr.apply (cp) + self.append_to_body (cp) + # new page-count: + for i in meta_counts : + self._set_meta (i, count * self._get_meta (i)) + # we have added count-1 paragraphs, because each page-break is a + # paragraph. + p = 'paragraph-count' + self._set_meta \ + (p, self._get_meta (p, classname = 'Set_Attribute') + (count - 1)) + self.assemble_body () + # end def apply +# end class Mailmerge + +def tree_serialise (element, prefix = '', mimetype = mimetypes [1]) : + """ Serialise a style-element of an OOo document (e.g., a + style:font-decl, style:default-style, etc declaration). + We remove the name of the style and return something that is a + representation of the style element which can be used as a + dictionary key. + The serialisation format is a tuple containing the tag as the + first item, the attributes (as key,value pairs returned by + items()) as the second item and the following items are + serialisations of children. + """ + attr = dict (element.attrib) + stylename = OOo_Tag ('style', 'name', mimetype) + if stylename in attr : del attr [stylename] + attr = attr.items () + attr.sort () + attr = tuple (attr) + serial = [prefix + element.tag, attr] + for e in element : + serial.append (tree_serialise (e, prefix, mimetype)) + return tuple (serial) +# end def tree_serialise + +class Concatenate (_Body_Concat) : + """ + This transformation is used to create a new document from a + concatenation of several documents. In the constructor we get a + list of documents to append to the master document. + """ + prio = 80 + style_containers = {} + ref_attrs = {} + for m in mimetypes : + style_containers.update \ + ({ OOo_Tag ('office', 'font-decls', m) : 1 + , OOo_Tag ('office', 'font-face-decls', m) : 1 + , OOo_Tag ('office', 'styles', m) : 1 + , OOo_Tag ('office', 'automatic-styles', m) : 1 + , OOo_Tag ('office', 'master-styles', m) : 1 + }) + # Cross-references in OOo document: + # 'attribute' references another element with 'tag'. + # If attribute names change, we must replace references, too. + # attribute : + # tag + ref_attrs.update \ + ({ OOo_Tag ('style', 'parent-style-name', m) : + OOo_Tag ('style', 'style', m) + , OOo_Tag ('style', 'master-page-name', m) : + OOo_Tag ('style', 'master-page', m) + , OOo_Tag ('style', 'page-layout-name', m) : # OOo 2.X + OOo_Tag ('style', 'page-layout', m) + , OOo_Tag ('style', 'page-master-name', m) : + OOo_Tag ('style', 'page-master', m) + , OOo_Tag ('table', 'style-name', m) : + OOo_Tag ('style', 'style', m) + , OOo_Tag ('text', 'style-name', m) : + OOo_Tag ('style', 'style', m) + , OOo_Tag ('draw', 'style-name', m) : + OOo_Tag ('style', 'style', m) + , OOo_Tag ('draw', 'text-style-name', m) : + OOo_Tag ('style', 'style', m) + }) + stylefiles = ['styles.xml', 'content.xml'] + oofiles = stylefiles + ['meta.xml'] + + body_decl_sections = ['variable-decl', 'sequence-decl'] + + def __init__ (self, * docs, ** kw) : + self.__super.__init__ (** kw) + self.docs = [] + for doc in docs : + self.docs.append (OOoPy (infile = doc)) + assert (self.docs [-1].mimetype == self.docs [0].mimetype) + # end def __init__ + + def apply_all (self, trees) : + assert (self.docs [0].mimetype == self.transformer.mimetype) + self.serialised = {} + self.stylenames = {} + self.namemaps = [{}] + self.tab_depend = {} + for s in self.ref_attrs.itervalues () : + self.namemaps [0][s] = {} + self.body_decls = {} + for s in self.body_decl_sections : + self.body_decls [s] = {} + self.trees = {} + for f in self.oofiles : + self.trees [f] = [trees [f].getroot ()] + self.sections = {} + for f in self.stylefiles : + self.sections [f] = {} + for node in self.trees [f][0] : + self.sections [f][node.tag] = node + for d in self.docs : + self.namemaps.append ({}) + for s in self.ref_attrs.itervalues () : + self.namemaps [-1][s] = {} + for f in self.oofiles : + self.trees [f].append (d.read (f).getroot ()) + # append a pagebreak style, will be optimized away if duplicate + pbs = Addpagebreak_Style (transformer = self.transformer) + pbs.apply (self.trees ['content.xml'][0]) + get_attr = [] + for attr in meta_counts : + a = self.oootag ('meta', attr) + t = self.oootag ('meta', 'document-statistic') + get_attr.append (Get_Attribute (t, a, 'concat-' + attr)) + zi = Attribute_Access \ + ( (Get_Max (None, self.oootag ('draw', 'z-index'), 'z-index'),) + , transformer = self.transformer + ) + zi.apply (self.trees ['content.xml'][0]) + self.zi = Attribute_Access \ + ( (Get_Max (None, self.oootag ('draw', 'z-index'), 'concat-z-index') + , + ) + , transformer = self.transformer + ) + self.getmeta = Attribute_Access \ + (get_attr, filename = 'meta.xml', transformer = self.transformer) + self.pbname = self.transformer \ + [':'.join (('Addpagebreak_Style', 'stylename'))] + for s in self.trees ['styles.xml'][0].findall \ + ('.//' + self.oootag ('style', 'default-style')) : + if s.get (self.oootag ('style', 'family')) == 'paragraph' : + default_style = s + break + self.default_properties = default_style.find \ + ('./' + self.properties_tag) + self.set_pagestyle () + for f in 'styles.xml', 'content.xml' : + self.style_merge (f) + self.body_concat () + self.append_pictures () + # end def apply_all + + def apply_tab_correction (self, node) : + """ Check if node depends on a style which has corrected tabs + if yes, insert all the default tabs *after* the maximum tab + position in that style. + """ + tab_stops = self.oootag ('style', 'tab-stops') + tab_stop = self.oootag ('style', 'tab-stop') + tab_pos = self.oootag ('style', 'position') + parent = node.get (self.oootag ('style', 'parent-style-name')) + if parent in self.tab_depend : + for prop in node : + if prop.tag != self.properties_tag : + continue + for sub in prop : + if sub.tag == tab_stops : + self.tab_depend [parent] = 1 + max = 0 + for ts in sub : + assert (ts.tag == tab_stop) + pos = float (ts.get (tab_pos) [:-2]) + if max < pos : + max = pos + self.insert_tabs (sub, max) + # end def apply_tab_correction + + def _attr_rename (self, idx) : + r = sum \ + ( [ set_attributes_from_dict (None, k, self.namemaps [idx][v]) + for k,v in self.ref_attrs.iteritems () + ] + , [] + ) + return Attribute_Access (r, transformer = self.transformer) + # end def _attr_rename + + def body_concat (self) : + count = {} + for i in meta_counts : + count [i] = self._get_meta (i) + count ['z-index'] = self._get_meta \ + ('z-index', classname = 'Get_Max') + 1 + pb = Addpagebreak \ + (stylename = self.pbname, transformer = self.transformer) + self.divide_body (self.trees ['content.xml'][0]) + self.body_decl (self.declarations, append = 0) + for idx in range (1, len (self.docs) + 1) : + meta = self.trees ['meta.xml'][idx] + content = self.trees ['content.xml'][idx] + tbody = self.find_tbody (content) + self.getmeta.apply (meta) + self.zi.apply (tbody) + + ra = Attribute_Access \ + ( ( Reanchor + (count ['page-count'], self.oootag ('draw', 'text-box')) + , Reanchor + (count ['page-count'], self.oootag ('draw', 'rect')) + , Reanchor + (count ['page-count'], self.oootag ('draw', 'frame')) + , Reanchor + (count ['z-index'], None, self.oootag ('draw', 'z-index')) + ) + , transformer = self.transformer # transformer added + ) + for i in meta_counts : + count [i] += self._get_meta (i, prefix = 'concat-') + count ['paragraph-count'] += 1 + count ['z-index'] += self._get_meta \ + ('z-index', classname = 'Get_Max', prefix = 'concat-') + 1 + namemap = self.namemaps [idx][self.oootag ('style', 'style')] + tr = self._attr_rename (idx) + pb.apply (self.bodyparts [-1]) + tr.apply (content) + ra.apply (content) + declarations = self._divide (tbody) + self.body_decl (declarations) + self.append_to_body (self.copyparts) + self.append_declarations () + self.assemble_body () + for i in meta_counts : + self._set_meta (i, count [i]) + # end def body_concat + + def body_decl (self, decl_section, append = 1) : + for sect in self.body_decl_sections : + s = self.declarations.find \ + ('.//' + self.oootag ('text', sect + 's')) + d = self.body_decls [sect] + t = self.oootag ('text', sect) + for n in decl_section.findall ('.//' + t) : + name = n.get (self.oootag ('text', 'name')) + if name not in d : + if append and s is not None : + s.append (n) + d [name] = 1 + # end def body_decl + + def insert_tabs (self, element, max = 0) : + """ Insert tab stops into the current element. Optionally after + max = the current maximum tab-position + """ + dist_tag = self.oootag ('style', 'tab-stop-distance') + for k in range (1, len (self.tab_correct)) : + if self.tab_correct [-k].isdigit() : + break + l = float (self.tab_correct [:-k]) + unit = self.tab_correct [-k:] + for ts in range (35) : + pos = l * (ts + 1) + if pos > max : + SubElement \ + ( element + , self.oootag ('style', 'tab-stop') + , { self.oootag ('style', 'position') : '%s%s' % (pos, unit) + } + ) + # end def insert_tabs + + def merge_defaultstyle (self, default_style, node) : + assert default_style is not None + assert node is not None + proppath = './' + self.properties_tag + defprops = default_style.find (proppath) + props = node.find (proppath) + sn = self.oootag ('style', 'name') + if props is None : + props = Element (self.properties_tag) + for k, v in defprops.attrib.iteritems () : + if self.default_properties.get (k) != v and not props.get (k) : + if k == self.oootag ('style', 'tab-stop-distance') : + self.tab_correct = v + self.tab_depend = {node.get (sn) : 1} + stps = SubElement \ + (props, self.oootag ('style', 'tab-stops')) + self.insert_tabs (stps) + else : + props.set (k,v) + if len (props) or props.attrib : + node.append (props) + # end def merge_defaultstyle + + def _newname (self, key, oldname) : + stylenum = 0 + if (key, oldname) not in self.stylenames : + self.stylenames [(key, oldname)] = 1 + return oldname + newname = basename = 'Concat_%s' % oldname + while (key, newname) in self.stylenames : + stylenum += 1 + newname = '%s%d' % (basename, stylenum) + self.stylenames [(key, newname)] = 1 + return newname + # end def _newname + + def set_pagestyle (self) : + """ For all documents: search for the first paragraph of the tbody + and get its style. Modify this style to include a reference + to the default page-style if it doesn't contain a reference + to a page style. Insert the new style into the list of + styles and modify the first paragraph to use the new page + style. + This procedure is necessary to make appended documents use + their page style instead of the master page style of the + first document. + FIXME: We should search the style hierarchy backwards for + the style of the first paragraph to check if there is a + reference to a page-style somewhere and not override the + page-style in this case. Otherwise appending complex + documents that use a different page-style for the first page + will not work if the page style is referenced in a style + from which the first paragraph style derives. + """ + for idx in range (1, len (self.docs) + 1) : + croot = self.trees ['content.xml'][idx] + sroot = self.trees ['styles.xml'] [idx] + tbody = self.find_tbody (croot) + para = tbody.find ('./' + self.oootag ('text', 'p')) + if para is None : + para = tbody.find ('./' + self.oootag ('text', 'list')) + tsn = self.oootag ('text', 'style-name') + sname = para.get (tsn) + styles = croot.find (self.oootag ('office', 'automatic-styles')) + ost = sroot.find (self.oootag ('office', 'styles')) + mst = sroot.find (self.oootag ('office', 'master-styles')) + assert mst is not None and len (mst) + assert mst [0].tag == self.oootag ('style', 'master-page') + sntag = self.oootag ('style', 'name') + master = mst [0].get (sntag) + mpn = self.oootag ('style', 'master-page-name') + stytag = self.oootag ('style', 'style') + style = None + for s in styles : + if s.tag == stytag : + # Explicit references to default style converted to + # explicit references to new page style. + if s.get (mpn) == '' : + s.set (mpn, master) + if s.get (sntag) == sname : + style = s + if style is None : + for s in ost : + if s.tag == stytag and s.get (sntag) == sname : + style = s + break + if style is not None and not style.get (mpn) : + newstyle = deepcopy (style) + # Don't register with newname: will be rewritten later + # when appending. We assume that an original doc does + # not already contain a style with _Concat suffix. + newname = sname + '_Concat' + para.set (tsn, newname) + newstyle.set (self.oootag ('style', 'name'), newname) + newstyle.set (mpn, master) + styles.append (newstyle) + # end def set_pagestyle + + def style_merge (self, oofile) : + """ Loop over all the docs in our document list and look up the + styles there. If a style matches an existing style in the + original document, register the style name for later + transformation if the style name in the original document + does not match the style name in the appended document. If + no match is found, append style to master document and add + to serialisation. If the style name already exists in the + master document, a new style name is created. Names of + parent styles are changed when appending -- this means that + parent style names already have to be defined earlier in the + document. + + If there is a reference to a parent style that is not yet + defined, and the parent style is defined later, it is + already too late, so an assertion is raised in this case. + OOo seems to ensure declaration order of dependent styles, + so this should not be a problem. + """ + for idx in range (len (self.trees [oofile])) : + namemap = self.namemaps [idx] + root = self.trees [oofile][idx] + delnode = [] + for nodeidx, node in enumerate (root) : + if node.tag not in self.style_containers : + continue + prefix = '' + # font_decls may have same name in styles.xml and content.xml + if node.tag == self.font_decls_tag : + prefix = oofile + default_style = None + for n in node : + if ( n.tag == self.oootag ('style', 'default-style') + and ( n.get (self.oootag ('style', 'family')) + == 'paragraph' + ) + ) : + default_style = n + name = n.get (self.oootag ('style', 'name'), None) + if not name : continue + if ( idx != 0 + and name == 'Standard' + and n.get (self.oootag ('style', 'class')) == 'text' + and ( n.get (self.oootag ('style', 'family')) + == 'paragraph' + ) + ) : + self.merge_defaultstyle (default_style, n) + self.apply_tab_correction (n) + key = prefix + n.tag + if key not in namemap : namemap [key] = {} + tr = self._attr_rename (idx) + tr.apply (n) + sn = tree_serialise (n, prefix, self.mimetype) + if sn in self.serialised : + newname = self.serialised [sn] + if name != newname : + assert \ + ( name not in namemap [key] + or namemap [key][name] == newname + ) + namemap [key][name] = newname + # optimize original doc: remove duplicate styles + if not idx and node.tag != self.font_decls_tag : + pass + #delnode.append (nodeidx) + else : + newname = self._newname (key, name) + self.serialised [sn] = newname + if newname != name : + n.set (self.oootag ('style', 'name'), newname) + dn = self.oootag ('style', 'display-name') + disp_name = n.get (dn) + if disp_name : + n.set (dn, 'Concat ' + disp_name) + namemap [key][name] = newname + if idx != 0 : + self.sections [oofile][node.tag].append (n) + assert not delnode or not idx + delnode.reverse () + for i in delnode : + del node [i] + # end style_merge + + def append_pictures (self) : + for doc in self.docs : + for f in doc.izip.infolist () : + if f.filename.startswith ('Pictures/') : + self.transformer.appendfiles.append \ + ((f.filename, doc.izip.read (f.filename))) + # end def append_pictures + +# end class Concatenate + +def renumber_frames (mimetype) : + return \ + [ Renumber (OOo_Tag ('draw', 'text-box', mimetype), 'Frame') # OOo 1.X + , Renumber (OOo_Tag ('draw', 'frame', mimetype), 'Frame') # OOo 2.X + ] +# end def renumber_frames + +def renumber_sections (mimetype) : + return [Renumber (OOo_Tag ('text', 'section', mimetype))] +# end def renumber_sections + +def renumber_tables (mimetype) : + return [Renumber (OOo_Tag ('table', 'table', mimetype))] +# end def renumber_tables + +def renumber_images (mimetype) : + return [Renumber (OOo_Tag ('draw', 'image', mimetype))] +# end def renumber_images + +def renumber_xml_id (mimetype) : + if mimetype == mimetypes [0] : + return [] + xmlid = OOo_Tag ('xml', 'id', mimetype) + return [Renumber (OOo_Tag ('text', 'list', mimetype), 'list', xmlid)] +# end def renumber_xml_id + +def renumber_all (mimetype) : + """ Factory function for all renumberings parameterized with + mimetype + """ + return Attribute_Access \ + ( renumber_frames (mimetype) + + renumber_sections (mimetype) + + renumber_tables (mimetype) + + renumber_images (mimetype) + + renumber_xml_id (mimetype) + ) +# end def renumber_all + +# used to have a separate Pagecount transform -- generalized to get +# some of the meta information using an Attribute_Access transform +# and set the same information later after possibly being updated by +# other transforms. We use another naming convention here for storing +# the info retrieved from the OOo document: We use the attribute name in +# the meta-information to store (and later retrieve) the information. + +def get_meta (mimetype) : + """ Factory function for Attribute_Access to get all interesting + meta-data + """ + get_attr = [] + for attr in meta_counts : + a = OOo_Tag ('meta', attr, mimetype) + t = OOo_Tag ('meta', 'document-statistic', mimetype) + get_attr.append (Get_Attribute (t, a, attr)) + return Attribute_Access (get_attr, prio = 20, filename = 'meta.xml') +# end def get_meta + +def set_meta (mimetype) : + """ Factory function for Attribute_Access to set all interesting + meta-data + """ + set_attr = [] + for attr in meta_counts : + a = OOo_Tag ('meta', attr, mimetype) + t = OOo_Tag ('meta', 'document-statistic', mimetype) + set_attr.append (Set_Attribute (t, a, attr)) + return Attribute_Access (set_attr, prio = 120, filename = 'meta.xml') +# end def set_meta diff --git a/OOoPy-1.11/ooopy/Version.py b/OOoPy-1.11/ooopy/Version.py new file mode 100644 index 0000000..495ca24 --- /dev/null +++ b/OOoPy-1.11/ooopy/Version.py @@ -0,0 +1 @@ +VERSION="1.11" diff --git a/OOoPy-1.11/ooopy/__init__.py b/OOoPy-1.11/ooopy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OOoPy-1.11/run_doctest.py b/OOoPy-1.11/run_doctest.py new file mode 100644 index 0000000..f96bd35 --- /dev/null +++ b/OOoPy-1.11/run_doctest.py @@ -0,0 +1,94 @@ +from __future__ import print_function +import doctest +import os +import sys + +if sys.version.startswith ('2.3') : + # Doctest has a bug with super in python 2.3. This patches the 2.3 + # doctest according to the patch by Christian Tanzer on sourceforge + # -- the fix is already in 2.4 but according to the docs on + # sourceforge will not be backported to 2.3. See + # http://sf.net/tracker/?func=detail&atid=105470&aid=902628&group_id=5470 + # http://mail.python.org/pipermail/python-bugs-list/2004-July/024211.html + class Tester_patched (doctest.Tester) : + __record_outcome = doctest.Tester._Tester__record_outcome + def rundoc (self, obj, name = None) : + if name is None: + try: + name = obj.__name__ + except AttributeError : + raise ValueError("Tester.rundoc: name must be given " + "when obj.__name__ doesn't exist; " + repr (obj)) + if self.verbose: + print ("Running", name + ".__doc__") + f, t = doctest.run_docstring_examples \ + ( obj, self.globs, self.verbose, name + , self.compileflags, self.optionflags + ) + if self.verbose: + print (f, "of", t, "examples failed in", name + ".__doc__") + self.__record_outcome(name, f, t) + if doctest._isclass(obj): + # In 2.2, class and static methods complicate life. Build + # a dict "that works", by hook or by crook. + d = {} + for tag, kind, homecls, value in doctest._classify_class_attrs(obj): + + if homecls is not obj: + # Only look at names defined immediately by the class. + continue + + elif self.isprivate(name, tag): + continue + + elif kind == "method": + if not isinstance(value, super): + # value is already a function + d[tag] = value + + elif kind == "static method": + # value isn't a function, but getattr reveals one + d[tag] = getattr(obj, tag) + + elif kind == "class method": + d[tag] = getattr(obj, tag).im_func + + elif kind == "property": + # The methods implementing the property have their + # own docstrings -- but the property may have one too. + if value.__doc__ is not None: + d[tag] = str(value.__doc__) + + elif kind == "data": + # Grab nested classes. + if doctest._isclass(value): + d[tag] = value + + else: + raise ValueError("teach doctest about %r" % kind) + f2, t2 = self.run__test__(d, name) + f += f2 + t += t2 + + return f, t + doctest.Tester_orig = doctest.Tester + doctest.Tester = Tester_patched + +format = "%(file)s fails %(f)s of %(t)s doc-tests" +for a in sys.argv [1:] : + sys.path [0:0] = ["./", os.path.dirname (a)] + os.environ ['PYTHONPATH'] = ':'.join (sys.path) + m = os.path.splitext (os.path.basename (a)) [0] + try : + module = __import__ (m) + file = module.__file__ + f, t = doctest.testmod (module, verbose = 0) + except KeyboardInterrupt : + raise + except Exception as cause : + print ("Testing of %s resulted in exception" % (a,)) + raise + else : + print (format % locals ()) + del sys.path [0:2] + diff --git a/OOoPy-1.11/setup.py b/OOoPy-1.11/setup.py new file mode 100644 index 0000000..9b3836e --- /dev/null +++ b/OOoPy-1.11/setup.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2005 Dr. Ralf Schlatterbeck Open Source Consulting. +# Reichergasse 131, A-3411 Weidling. +# Web: http://www.runtux.com Email: office@runtux.com +# All rights reserved +# **************************************************************************** +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# **************************************************************************** + +from distutils.core import setup +try : + from ooopy.Version import VERSION +except : + VERSION = None + +description = [] +f = open ('README.rst') +logo_stripped = False +for line in f : + if not logo_stripped and line.strip () : + continue + logo_stripped = True + description.append (line) + +license = 'GNU Library or Lesser General Public License (LGPL)' +download = 'http://downloads.sourceforge.net/project/ooopy/ooopy' + +setup \ + ( name = "OOoPy" + , version = VERSION + , description = "OOoPy: Modify OpenOffice.org documents in Python" + , long_description = ''.join (description) + , license = license + , author = "Ralf Schlatterbeck" + , author_email = "rsc@runtux.com" + , url = "http://ooopy.sourceforge.net/" + , download_url = \ + "%(download)s/%(VERSION)s/OOoPy-%(VERSION)s.tar.gz" % locals () + , packages = ['ooopy'] + , platforms = 'Any' + , data_files = + [ ('share/ooopy' + , [ 'run_doctest.py' + , 'testfiles/carta.odt' + , 'testfiles/carta.stw' + , 'testfiles/rechng.odt' + , 'testfiles/rechng.sxw' + , 'testfiles/testenum.odt' + , 'testfiles/test.odt' + , 'testfiles/test.sxw' + , 'testfiles/x.csv' + ] + ) + ] + , scripts = + [ 'bin/ooo_as_text' + , 'bin/ooo_cat' + , 'bin/ooo_fieldreplace' + , 'bin/ooo_grep' + , 'bin/ooo_mailmerge' + ] + , classifiers = + [ 'Development Status :: 5 - Production/Stable' + , 'License :: OSI Approved :: ' + license + , 'Operating System :: OS Independent' + , 'Programming Language :: Python' + , 'Topic :: Internet :: WWW/HTTP :: Dynamic Content' + , 'Topic :: Office/Business :: Office Suites' + , 'Topic :: Text Processing' + , 'Topic :: Text Processing :: General' + , 'Topic :: Text Processing :: Markup :: XML' + , 'Topic :: Text Editors :: Word Processors' + ] + ) diff --git a/OOoPy-1.11/testfiles/carta.odt b/OOoPy-1.11/testfiles/carta.odt new file mode 100644 index 0000000000000000000000000000000000000000..87f1914090603ed351a43f407cbdf61aedabc499 GIT binary patch literal 30000 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 K3gVk1uKouJrTy{% literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/carta.stw b/OOoPy-1.11/testfiles/carta.stw new file mode 100644 index 0000000000000000000000000000000000000000..503d571e64549feeb272ea8bb34474bf6e07d8a6 GIT binary patch literal 26692 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%0A%TNLd?GO@ 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 literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/rechng.odt b/OOoPy-1.11/testfiles/rechng.odt new file mode 100644 index 0000000000000000000000000000000000000000..aeccf190c8cb4ba982483e3b543783d32906ef06 GIT binary patch literal 14629 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 literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/rechng.sxw b/OOoPy-1.11/testfiles/rechng.sxw new file mode 100644 index 0000000000000000000000000000000000000000..865654a3c99d2dce6a3f3daf2636a35c66ce08cb GIT binary patch literal 8963 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 literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/tbl_first.odt b/OOoPy-1.11/testfiles/tbl_first.odt new file mode 100644 index 0000000000000000000000000000000000000000..e4faca1af6db394649610157220b7841a59486f8 GIT binary patch literal 8547 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 bnAgqU#AX$Fbd1Z_h%P=37x8EEkEQt^{VGWL literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/tbl_second.odt b/OOoPy-1.11/testfiles/tbl_second.odt new file mode 100644 index 0000000000000000000000000000000000000000..c2cb05ff73e10759c8aba81d67d242f42a719c88 GIT binary patch literal 9475 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 DE=3!; literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/test.odt b/OOoPy-1.11/testfiles/test.odt new file mode 100644 index 0000000000000000000000000000000000000000..51f966617002cf72e19fb62f480529af1ab76117 GIT binary patch literal 11031 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 J0@1fk_J6S%;tK!( literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/test.sxw b/OOoPy-1.11/testfiles/test.sxw new file mode 100644 index 0000000000000000000000000000000000000000..b32b04bcb290f19e7cb2205b68779d730825fa60 GIT binary patch literal 6775 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 S>j3}?;?L?B06@ulQ2RfkHlPOp literal 0 HcmV?d00001 diff --git a/OOoPy-1.11/testfiles/testenum.odt b/OOoPy-1.11/testfiles/testenum.odt new file mode 100644 index 0000000000000000000000000000000000000000..e974521815d05e9d6dc7f68ac0062d3f59dcaab9 GIT binary patch literal 12284 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