# HG changeset patch # User Stephan Peijnik # Date 1286816093 -3600 # Node ID b8cc53d22545706b28c7a26dffd24f192a76541a # Parent fbce8e403470db8c9e580a5efd9d717cd2260c1f Replace pyxml/xmlproc-based XML validator with lxml based one Pyxml/xmlproc is being used in tools/xen/xm/xenapi_create.py but is unmaintained for several years now. xmlproc is used only for validating XML documents against a DTD file. This patch replaces the pyxml/xmlproc based XML validation with code based on lxml, which is actively maintained. Signed-off-by: Stephan Peijnik Signed-off-by: Stefano Stabellini committer: Stefano Stabellini Index: xen-4.0.1-testing/README =================================================================== --- xen-4.0.1-testing.orig/README +++ xen-4.0.1-testing/README @@ -137,12 +137,15 @@ Python Runtime Libraries Xend (the Xen daemon) has the following runtime dependencies: * Python 2.3 or later. - In many distros, the XML-aspects to the standard library + In some distros, the XML-aspects to the standard library (xml.dom.minidom etc) are broken out into a separate python-xml package. This is also required. + In more recent versions of Debian and Ubuntu the XML-aspects are included + in the base python package however (python-xml has been removed + from Debian in squeeze and from Ubuntu in intrepid). URL: http://www.python.org/ - Debian: python, python-xml + Debian: python * For optional SSL support, pyOpenSSL: URL: http://pyopenssl.sourceforge.net/ @@ -153,8 +156,9 @@ Xend (the Xen daemon) has the following Debian: python-pam * For optional XenAPI support in XM, PyXML: - URL: http://pyxml.sourceforge.net - YUM: PyXML + URL: http://codespeak.net/lxml/ + Debian: python-lxml + YUM: python-lxml Intel(R) Trusted Execution Technology Support Index: xen-4.0.1-testing/tools/python/xen/xm/xenapi_create.py =================================================================== --- xen-4.0.1-testing.orig/tools/python/xen/xm/xenapi_create.py +++ xen-4.0.1-testing/tools/python/xen/xm/xenapi_create.py @@ -14,13 +14,15 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2007 Tom Wilkie +# Copyright (C) 2010 ANEXIA Internetdienstleistungs GmbH +# Author: Stephan Peijnik #============================================================================ """Domain creation using new XenAPI """ from xen.xm.main import server, get_default_SR from xml.dom.minidom import parse, getDOMImplementation -from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd +from lxml import etree from xen.xend import sxp from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \ XEN_API_ON_CRASH_BEHAVIOUR @@ -35,6 +37,7 @@ import os from os.path import join import traceback import re +import warnings # Used by lxml-based validator def log(_, msg): #print "> " + msg @@ -118,12 +121,21 @@ class xenapi_create: Use this if possible as it gives nice error messages """ - dtd = xmldtd.load_dtd(self.dtd) - parser = xmlproc.XMLProcessor() - parser.set_application(xmlval.ValidatingApp(dtd, parser)) - parser.dtd = dtd - parser.ent = dtd - parser.parse_resource(file) + try: + dtd = etree.DTD(open(self.dtd, 'r')) + except IOError: + # The old code did neither raise an exception here, nor + # did it report an error. For now we issue a warning. + # TODO: How to handle a missing dtd file? + # --sp + warnings.warn('DTD file %s not found.' % (self.dtd), + UserWarning) + return + + tree = etree.parse(file) + root = tree.getroot() + if not dtd.validate(root): + self.handle_dtd_errors(dtd) def check_dom_against_dtd(self, dom): """ @@ -131,49 +143,36 @@ class xenapi_create: Doesn't give as nice error messages. (no location info) """ - dtd = xmldtd.load_dtd(self.dtd) - app = xmlval.ValidatingApp(dtd, self) - app.set_locator(self) - self.dom2sax(dom, app) - - # Get errors back from ValidatingApp - def report_error(self, number, args=None): - self.errors = xmlproc.errors.english try: - msg = self.errors[number] - if args != None: - msg = msg % args - except KeyError: - msg = self.errors[4002] % number # Unknown err msg :-) - print msg + dtd = etree.DTD(open(self.dtd, 'r')) + except IOError: + # The old code did neither raise an exception here, nor + # did it report an error. For now we issue a warning. + # TODO: How to handle a missing dtd file? + # --sp + warnings.warn('DTD file %s not found.' % (self.dtd), + UserWarning) + return + + # XXX: This may be a bit slow. Maybe we should use another way + # of getting an etree root element from the minidom DOM tree... + # -- sp + root = etree.XML(dom.toxml()) + if not dtd.validate(root): + self.handle_dtd_errors(dtd) + + # Do the same that was done in report_error before. This is directly + # called by check_dtd and check_dom_against_dtd. + # We are using sys.stderr instead of print though (python3k clean). + def handle_dtd_errors(self, dtd): + # XXX: Do we really want to bail out here? + # -- sp + for err in dtd.error_log: + err_str = 'ERROR: %s\n' % (str(err),) + sys.stderr.write(err_str) + sys.stderr.flush() sys.exit(-1) - # Here for compatibility with ValidatingApp - def get_line(self): - return -1 - - def get_column(self): - return -1 - - def dom2sax(self, dom, app): - """ - Take a dom tree and tarverse it, - issuing SAX calls to app. - """ - for child in dom.childNodes: - if child.nodeType == child.TEXT_NODE: - data = child.nodeValue - app.handle_data(data, 0, len(data)) - else: - app.handle_start_tag( - child.nodeName, - self.attrs_to_dict(child.attributes)) - self.dom2sax(child, app) - app.handle_end_tag(child.nodeName) - - def attrs_to_dict(self, attrs): - return dict(attrs.items()) - # # Checks which cannot be done with dtd #