annotate bitten/build/xmltools.py @ 908:56c269e75737 0.6.x

Ported r989 back to 0.6.x branch.
author cmlenz
date Wed, 13 Apr 2011 13:25:27 +0000
parents f4d07544722b
children
rev   line source
379
0df178e07fdb Use UTF-8 as encoding of source files.
cmlenz
parents: 313
diff changeset
1 # -*- coding: utf-8 -*-
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
2 #
408
933105ab516b Update file headers and other stuff pointing to the old home.
cmlenz
parents: 379
diff changeset
3 # Copyright (C) 2005-2007 Christopher Lenz <cmlenz@gmx.de>
833
f4d07544722b 0.6dev: Merged [910] from trunk.
osimons
parents: 514
diff changeset
4 # Copyright (C) 2007-2010 Edgewall Software
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
5 # All rights reserved.
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
6 #
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
7 # This software is licensed as described in the file COPYING, which
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
8 # you should have received as part of this distribution. The terms
408
933105ab516b Update file headers and other stuff pointing to the old home.
cmlenz
parents: 379
diff changeset
9 # are also available at http://bitten.edgewall.org/wiki/License.
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
10
313
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
11 """Recipe commands for XML processing."""
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
12
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
13 import logging
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
14 import os
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
15
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
16 try:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
17 import libxml2
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
18 import libxslt
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
19 have_libxslt = True
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
20 except ImportError:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
21 have_libxslt = False
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
22
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
23 if not have_libxslt and os.name == 'nt':
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
24 try:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
25 import win32com.client
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
26 have_msxml = True
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
27 except ImportError:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
28 have_msxml = False
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
29 else:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
30 have_msxml = False
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
31
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
32 log = logging.getLogger('bitten.build.xmltools')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
33
411
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
34 __docformat__ = 'restructuredtext en'
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
35
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
36 def transform(ctxt, src=None, dest=None, stylesheet=None):
313
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
37 """Apply an XSLT stylesheet to a source XML document.
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
38
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
39 This command requires either libxslt (with Python bindings), or MSXML to
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
40 be installed.
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
41
411
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
42 :param ctxt: the build context
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
43 :type ctxt: `Context`
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
44 :param src: name of the XML input file
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
45 :param dest: name of the XML output file
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
46 :param stylesheet: name of the file containing the XSLT stylesheet
313
90422699a594 More and improved docstrings (using epydoc format).
cmlenz
parents: 248
diff changeset
47 """
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
48 assert src, 'Missing required attribute "src"'
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
49 assert dest, 'Missing required attribute "dest"'
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
50 assert stylesheet, 'Missing required attribute "stylesheet"'
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
51
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
52 if have_libxslt:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
53 log.debug('Using libxslt for XSLT transformation')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
54 srcdoc, styledoc, result = None, None, None
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
55 try:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
56 srcdoc = libxml2.parseFile(ctxt.resolve(src))
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
57 styledoc = libxslt.parseStylesheetFile(ctxt.resolve(stylesheet))
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
58 result = styledoc.applyStylesheet(srcdoc, None)
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
59 styledoc.saveResultToFilename(ctxt.resolve(dest), result, 0)
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
60 finally:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
61 if styledoc:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
62 styledoc.freeStylesheet()
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
63 if srcdoc:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
64 srcdoc.freeDoc()
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
65 if result:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
66 result.freeDoc()
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
67
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
68 elif have_msxml:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
69 log.debug('Using MSXML for XSLT transformation')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
70 srcdoc = win32com.client.Dispatch('MSXML2.DOMDocument.3.0')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
71 if not srcdoc.load(ctxt.resolve(src)):
514
2187988ae4d4 Fix wrong variable name - fixes #328
dfraser
parents: 436
diff changeset
72 err = srcdoc.parseError
908
56c269e75737 Ported r989 back to 0.6.x branch.
cmlenz
parents: 833
diff changeset
73 ctxt.error('Failed to parse XML source %s: %s' % (src, err.reason))
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
74 return
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
75 styledoc = win32com.client.Dispatch('MSXML2.DOMDocument.3.0')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
76 if not styledoc.load(ctxt.resolve(stylesheet)):
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
77 err = styledoc.parseError
908
56c269e75737 Ported r989 back to 0.6.x branch.
cmlenz
parents: 833
diff changeset
78 ctxt.error('Failed to parse XSLT stylesheet %s: %s' %
56c269e75737 Ported r989 back to 0.6.x branch.
cmlenz
parents: 833
diff changeset
79 (stylesheet, err.reason))
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
80 return
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
81 result = srcdoc.transformNode(styledoc)
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
82
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
83 # MSXML seems to always write produce the resulting XML document using
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
84 # UTF-16 encoding, regardless of the encoding specified in the
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
85 # stylesheet. For better interoperability, recode to UTF-8 here.
248
15d8d8c809f0 Some minor fixes:
cmlenz
parents: 243
diff changeset
86 result = result.encode('utf-8').replace(' encoding="UTF-16"?>', '?>')
243
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
87
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
88 dest_file = file(ctxt.resolve(dest), 'w')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
89 try:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
90 dest_file.write(result)
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
91 finally:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
92 dest_file.close()
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
93
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
94 else:
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
95 ctxt.error('No usable XSLT implementation found')
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
96
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
97 # TODO: as a last resort, try to invoke 'xsltproc' to do the
e75816cb2f45 * Add an <x:transform/> task for applying XSLT transformations. Can use either libxslt or MSXML if available. Closes #35.
cmlenz
parents:
diff changeset
98 # transformation?
Copyright (C) 2012-2017 Edgewall Software