Edgewall Software

source: trunk/bitten/build/xmltools.py @ 1001

Last change on this file since 1001 was 989, checked in by cmlenz, 13 years ago

Fix for incorrect error reporting in XML transform command when using the MSXML implementation.

  • Property svn:eol-style set to native
File size: 3.3 KB
CovLine 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2005-2007 Christopher Lenz <cmlenz@gmx.de>
4# Copyright (C) 2007-2010 Edgewall Software
5# All rights reserved.
6#
7# This software is licensed as described in the file COPYING, which
8# you should have received as part of this distribution. The terms
9# are also available at http://bitten.edgewall.org/wiki/License.
10
111"""Recipe commands for XML processing."""
12
113import logging
114import os
15
116try:
117    import libxml2
118    import libxslt
119    have_libxslt = True
020except ImportError:
021    have_libxslt = False
22
123if not have_libxslt and os.name == 'nt':
024    try:
025        import win32com.client
026        have_msxml = True
027    except ImportError:
028        have_msxml = False
029else:
130    have_msxml = False
31
132log = logging.getLogger('bitten.build.xmltools')
33
134__docformat__ = 'restructuredtext en'
35
136def transform(ctxt, src=None, dest=None, stylesheet=None):
37    """Apply an XSLT stylesheet to a source XML document.
38   
39    This command requires either libxslt (with Python bindings), or MSXML to
40    be installed.
41   
42    :param ctxt: the build context
43    :type ctxt: `Context`
44    :param src: name of the XML input file
45    :param dest: name of the XML output file
46    :param stylesheet: name of the file containing the XSLT stylesheet
47    """
448    assert src, 'Missing required attribute "src"'
349    assert dest, 'Missing required attribute "dest"'
250    assert stylesheet, 'Missing required attribute "stylesheet"'
51
152    if have_libxslt:
153        log.debug('Using libxslt for XSLT transformation')
154        srcdoc, styledoc, result = None, None, None
155        try:
156            srcdoc = libxml2.parseFile(ctxt.resolve(src))
157            styledoc = libxslt.parseStylesheetFile(ctxt.resolve(stylesheet))
158            result = styledoc.applyStylesheet(srcdoc, None)
159            styledoc.saveResultToFilename(ctxt.resolve(dest), result, 0)
160        finally:
161            if styledoc:
162                styledoc.freeStylesheet()
163            if srcdoc:
164                srcdoc.freeDoc()
165            if result:
166                result.freeDoc()
67
068    elif have_msxml:
069        log.debug('Using MSXML for XSLT transformation')
070        srcdoc = win32com.client.Dispatch('MSXML2.DOMDocument.3.0')
071        if not srcdoc.load(ctxt.resolve(src)):
072            err = srcdoc.parseError
073            ctxt.error('Failed to parse XML source %s: %s' % (src, err.reason))
074            return
075        styledoc = win32com.client.Dispatch('MSXML2.DOMDocument.3.0')
076        if not styledoc.load(ctxt.resolve(stylesheet)):
077            err = styledoc.parseError
078            ctxt.error('Failed to parse XSLT stylesheet %s: %s' %
079                       (stylesheet, err.reason))
080            return
081        result = srcdoc.transformNode(styledoc)
82
83        # MSXML seems to always write produce the resulting XML document using
84        # UTF-16 encoding, regardless of the encoding specified in the
85        # stylesheet. For better interoperability, recode to UTF-8 here.
086        result = result.encode('utf-8').replace(' encoding="UTF-16"?>', '?>')
87
088        dest_file = file(ctxt.resolve(dest), 'w')
089        try:
090            dest_file.write(result)
091        finally:
092            dest_file.close()
93
094    else:
095        ctxt.error('No usable XSLT implementation found')
96
97        # TODO: as a last resort, try to invoke 'xsltproc' to do the
98        #       transformation?
Note: See TracBrowser for help on using the repository browser.