From d93e2c421eafbd22de171c9356892d5d03476de7 Mon Sep 17 00:00:00 2001 From: rlskoeser Date: Mon, 28 Jan 2013 17:47:05 -0500 Subject: [PATCH] handle xsl transform that returns an empty result --- CHANGELOG | 8 ++++++++ eulxml/xmlmap/core.py | 16 ++++++++++++---- test/test_xmlmap/test_core.py | 12 ++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 23b0e9d..8a1c4ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,14 @@ any necessary information about installation or upgrade notes. * Corrected a minor bug where schema validation errors were not cleared between multiple validations. +* To avoid permission denied warning for auto-generated parser files, + parsetab files are now created in python tempdir if the running user + doesn't have write permission in the package installation directory. + [`Issue 1 `_] +* When an XSLT transformation results in an empty document, + :meth:`eulxml.xmlap.XmlObject.xsl_transform` now returns None. + [`Issue 6 `_] +* 0.18.0 - Formset Ordering and DateTime diff --git a/eulxml/xmlmap/core.py b/eulxml/xmlmap/core.py index 50f89e5..5315b31 100644 --- a/eulxml/xmlmap/core.py +++ b/eulxml/xmlmap/core.py @@ -23,12 +23,12 @@ from lxml import etree from lxml.builder import ElementMaker -from eulxml.xmlmap.fields import Field, NodeList +from eulxml.xmlmap.fields import Field logger = logging.getLogger(__name__) -__all__ = [ 'XmlObject', 'parseUri', 'parseString', 'loadSchema', - 'load_xmlobject_from_string', 'load_xmlobject_from_file' ] +__all__ = ['XmlObject', 'parseUri', 'parseString', 'loadSchema', + 'load_xmlobject_from_string', 'load_xmlobject_from_file'] # NB: When parsing XML in this module, we explicitly create a new parser # each time. Without this, lxml 2.2.7 uses a global default parser. When @@ -374,7 +374,15 @@ def xsl_transform(self, filename=None, xsl=None, return_type=None, **params): # - to output xml result, use serialize instead of unicode if return_type is None: return_type = XmlObject - return return_type(transform(self.node)) + + result = transform(self.node) + # If XSLT returns nothing, transform returns an _XSLTResultTree + # with no root node. Log a warning, and don't generate an + # empty xmlobject which will behave unexpectedly. + if result is None or result.getroot() is None: + logger.warning("XSL transform generated an empty result") + else: + return return_type(result) def __unicode__(self): if isinstance(self.node, basestring): diff --git a/test/test_xmlmap/test_core.py b/test/test_xmlmap/test_core.py index a22bd84..94a3c0a 100755 --- a/test/test_xmlmap/test_core.py +++ b/test/test_xmlmap/test_core.py @@ -63,6 +63,12 @@ class TestXsl(unittest.TestCase): ''' + EMPTY_RESULT_XSL = ''' + + + + ''' + def setUp(self): # parseString wants a url. let's give it a proper one. url = '%s#%s.%s' % (__file__, self.__class__.__name__, 'FIXTURE_TEXT') @@ -89,6 +95,12 @@ class TestObject(xmlmap.XmlObject): self.assertEqual('42', newobj.nobar_baz) self.assertEqual(None, newobj.bar_baz) + # empty result + obj = TestObject(self.fixture) + self.assertEqual(None, obj.xsl_transform(xsl=self.EMPTY_RESULT_XSL, + return_type=TestObject), + 'xsl transform should return None for an empty XSLT result') + self.FILE.close() # not yet tested: xsl with parameters