merge stable
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Wed, 08 Jul 2009 10:45:31 +0200
branchstable
changeset 2326 05ae71d9a069
parent 2325 363b66a15668 (current diff)
parent 2321 0b363cd5ef76 (diff)
child 2327 2aa28ac13d64
child 2339 00b704535984
merge
web/views/facets.py
--- a/common/uilib.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/common/uilib.py	Wed Jul 08 10:45:31 2009 +0200
@@ -15,7 +15,7 @@
 from urllib import quote as urlquote
 from StringIO import StringIO
 
-from logilab.mtconverter import html_escape, html_unescape
+from logilab.mtconverter import xml_escape, html_unescape
 
 from cubicweb.utils import ustrftime
 
@@ -66,7 +66,7 @@
 except ImportError:
     def rest_publish(entity, data):
         """default behaviour if docutils was not found"""
-        return html_escape(data)
+        return xml_escape(data)
 
 TAG_PROG = re.compile(r'</?.*?>', re.U)
 def remove_html_tags(text):
@@ -108,7 +108,7 @@
     if len(text_nohtml) <= length:
         return text
     # else if un-tagged text is too long, cut it
-    return html_escape(text_nohtml[:length] + u'...')
+    return xml_escape(text_nohtml[:length] + u'...')
 
 fallback_safe_cut = safe_cut
 
@@ -220,12 +220,12 @@
             attrs['class'] = attrs.pop('klass')
         except KeyError:
             pass
-        value += u' ' + u' '.join(u'%s="%s"' % (attr, html_escape(unicode(value)))
+        value += u' ' + u' '.join(u'%s="%s"' % (attr, xml_escape(unicode(value)))
                                   for attr, value in sorted(attrs.items())
                                   if value is not None)
     if content:
         if escapecontent:
-            content = html_escape(unicode(content))
+            content = xml_escape(unicode(content))
         value += u'>%s</%s>' % (content, tag)
     else:
         value += u'/>'
@@ -406,9 +406,9 @@
         strings.append(body)
         strings.append(u'</div>')
     if title:
-        strings.append(u'<h1 class="error">%s</h1>'% html_escape(title))
+        strings.append(u'<h1 class="error">%s</h1>'% xml_escape(title))
     try:
-        strings.append(u'<p class="error">%s</p>' % html_escape(str(exception)).replace("\n","<br />"))
+        strings.append(u'<p class="error">%s</p>' % xml_escape(str(exception)).replace("\n","<br />"))
     except UnicodeError:
         pass
     strings.append(u'<div class="error_traceback">')
@@ -416,9 +416,9 @@
         strings.append(u'<b>File</b> <b class="file">%s</b>, <b>line</b> '
                        u'<b class="line">%s</b>, <b>function</b> '
                        u'<b class="function">%s</b>:<br/>'%(
-            html_escape(stackentry[0]), stackentry[1], html_escape(stackentry[2])))
+            xml_escape(stackentry[0]), stackentry[1], xml_escape(stackentry[2])))
         if stackentry[3]:
-            string = html_escape(stackentry[3]).decode('utf-8', 'replace')
+            string = xml_escape(stackentry[3]).decode('utf-8', 'replace')
             strings.append(u'&nbsp;&nbsp;%s<br/>\n' % (string))
         # add locals info for each entry
         try:
@@ -426,7 +426,7 @@
             html_info = []
             chars = 0
             for name, value in local_context.iteritems():
-                value = html_escape(repr(value))
+                value = xml_escape(repr(value))
                 info = u'<span class="name">%s</span>=%s, ' % (name, value)
                 line_length = len(name) + len(value)
                 chars += line_length
@@ -491,5 +491,5 @@
     def newfunc(*args, **kwargs):
         ret = function(*args, **kwargs)
         assert isinstance(ret, basestring)
-        return html_escape(ret)
+        return xml_escape(ret)
     return newfunc
--- a/cwctl.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/cwctl.py	Wed Jul 08 10:45:31 2009 +0200
@@ -733,7 +733,7 @@
         mih = config.migration_handler()
         if args:
             for arg in args:
-                mih.process_script(script)
+                mih.process_script(arg)
         else:
             mih.interactive_shell()
         mih.shutdown()
--- a/doc/book/en/development/datamodel/define-workflows.rst	Wed Jul 08 10:44:37 2009 +0200
+++ b/doc/book/en/development/datamodel/define-workflows.rst	Wed Jul 08 10:45:31 2009 +0200
@@ -118,7 +118,7 @@
 * `%(seid)s`, the object's current state eid
 
 
-.. image:: images/lax-book.03-transitions-view.en.png
+.. image:: ../../images/lax-book.03-transitions-view.en.png
 
 You can notice that in the action box of a BlogEntry, the state
 is now listed as well as the possible transitions defined by the workflow.
--- a/entity.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/entity.py	Wed Jul 08 10:45:31 2009 +0200
@@ -13,7 +13,7 @@
 from logilab.common.compat import all
 from logilab.common.decorators import cached
 from logilab.common.deprecation import obsolete
-from logilab.mtconverter import TransformData, TransformError, html_escape
+from logilab.mtconverter import TransformData, TransformError, xml_escape
 
 from rql.utils import rqlvar_maker
 
@@ -456,7 +456,7 @@
             return u''
         value = printable_value(self.req, attrtype, value, props, displaytime)
         if format == 'text/html':
-            value = html_escape(value)
+            value = xml_escape(value)
         return value
 
     def mtc_transform(self, data, format, target_format, encoding,
@@ -659,6 +659,7 @@
                     self.critical("can't get value for attribute %s of entity with eid %s",
                                   name, self.eid)
                     if self.e_schema.destination(name) == 'String':
+                        # XXX (syt) imo emtpy string is better
                         self[name] = value = self.req._('unaccessible')
                     else:
                         self[name] = value = None
--- a/ext/html4zope.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/ext/html4zope.py	Wed Jul 08 10:45:31 2009 +0200
@@ -24,7 +24,7 @@
 
 __docformat__ = 'reStructuredText'
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from docutils import nodes
 from docutils.writers.html4css1 import Writer as CSS1Writer
@@ -154,7 +154,7 @@
         error = u'System Message: %s%s/%s%s (%s %s)%s</p>\n' % (
             a_start, node['type'], node['level'], a_end,
             self.encode(node['source']), line, backref_text)
-        self.body.append(u'<div class="system-message"><b>ReST / HTML errors:</b>%s</div>' % html_escape(error))
+        self.body.append(u'<div class="system-message"><b>ReST / HTML errors:</b>%s</div>' % xml_escape(error))
 
     def depart_system_message(self, node):
         pass
--- a/ext/rest.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/ext/rest.py	Wed Jul 08 10:45:31 2009 +0200
@@ -29,7 +29,7 @@
 from docutils.parsers.rst import Parser, states, directives
 from docutils.parsers.rst.roles import register_canonical_role, set_classes
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import ESC_UCAR_TABLE, ESC_CAR_TABLE, xml_escape
 
 from cubicweb.ext.html4zope import Writer
 
@@ -207,8 +207,12 @@
     req = context.req
     if isinstance(data, unicode):
         encoding = 'unicode'
+        # remove unprintable characters unauthorized in xml
+        data = data.translate(ESC_UCAR_TABLE)
     else:
         encoding = req.encoding
+        # remove unprintable characters unauthorized in xml
+        data = data.translate(ESC_CAR_TABLE)
     settings = {'input_encoding': encoding, 'output_encoding': 'unicode',
                 'warning_stream': StringIO(), 'context': context,
                 # dunno what's the max, severe is 4, and we never want a crash
@@ -232,5 +236,5 @@
         LOGGER.exception('error while publishing ReST text')
         if not isinstance(data, unicode):
             data = unicode(data, encoding, 'replace')
-        return html_escape(req._('error while publishing ReST text')
+        return xml_escape(req._('error while publishing ReST text')
                            + '\n\n' + data)
--- a/goa/appobjects/components.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/goa/appobjects/components.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import typed_eid
 from cubicweb.selectors import one_line_rset, match_search_state, accept
@@ -74,7 +74,7 @@
         label = display_name(req, etype, 'plural')
         view = self.vreg.select_view('list', req, req.etype_rset(etype))
         url = view.url()
-        etypelink = u'&nbsp;<a href="%s">%s</a>' % (html_escape(url), label)
+        etypelink = u'&nbsp;<a href="%s">%s</a>' % (xml_escape(url), label)
         yield (label, etypelink, self.add_entity_link(eschema, req))
 
 ManageView.entity_types = entity_types_no_count
--- a/goa/appobjects/dbmgmt.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/goa/appobjects/dbmgmt.py	Wed Jul 08 10:45:31 2009 +0200
@@ -12,7 +12,7 @@
 from pickle import loads, dumps
 
 from logilab.common.decorators import cached
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import none_rset, match_user_groups
 from cubicweb.common.view import StartupView
@@ -54,7 +54,7 @@
                     break
         values.append('__session=%s' % cookie['__session'].value)
         self.w(u"<p>pass this flag to the client: --cookie='%s'</p>"
-               % html_escape('; '.join(values)))
+               % xml_escape('; '.join(values)))
 
 
 
@@ -148,7 +148,7 @@
                          % cpath)
                 self.w(u'<div>click <a href="%s?vid=contentclear">here</a> to '
                        '<b>delete all datastore content</b> so process can be '
-                       'reinitialized</div>' % html_escape(self.req.base_url()))
+                       'reinitialized</div>' % xml_escape(self.req.base_url()))
         Put(status)
 
     @property
@@ -159,11 +159,11 @@
                                              repo=self.config.repository())
 
     def msg(self, msg):
-        self.w(u'<div class="message">%s</div>' % html_escape(msg))
+        self.w(u'<div class="message">%s</div>' % xml_escape(msg))
     def redirect(self, msg):
         raise Redirect(self.req.build_url('', msg))
     def continue_link(self):
-        self.w(u'<a href="%s">continue</a><br/>' % html_escape(self.req.url()))
+        self.w(u'<a href="%s">continue</a><br/>' % xml_escape(self.req.url()))
 
 
 class ContentClear(StartupView):
--- a/selectors.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/selectors.py	Wed Jul 08 10:45:31 2009 +0200
@@ -79,7 +79,7 @@
         ret = selector(cls, *args, **kwargs)
         if TRACED_OIDS == 'all' or oid in TRACED_OIDS:
             #SELECTOR_LOGGER.warning('selector %s returned %s for %s', selname, ret, cls)
-            print 'selector %s returned %s for %s' % (selname, ret, vobj)
+            print '%s -> %s for %s' % (selname, ret, vobj)
         return ret
     traced.__name__ = selector.__name__
     return traced
--- a/server/__init__.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/server/__init__.py	Wed Jul 08 10:45:31 2009 +0200
@@ -50,8 +50,7 @@
     driver = source['db-driver']
     sqlcnx = repo.system_source.get_connection()
     sqlcursor = sqlcnx.cursor()
-    def execute(sql, args=None):
-        repo.system_source.doexec(sqlcursor, sql, args)
+    execute = sqlcursor.execute
     if drop:
         dropsql = sqldropschema(schema, driver)
         try:
--- a/server/session.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/server/session.py	Wed Jul 08 10:45:31 2009 +0200
@@ -88,9 +88,7 @@
         """return a sql cursor on the system database"""
         if not sql.split(None, 1)[0].upper() == 'SELECT':
             self.mode = 'write'
-        cursor = self.pool['system']
-        self.pool.source('system').doexec(cursor, sql, args)
-        return cursor
+        return self.pool.source('system').doexec(self, sql, args)
 
     def set_language(self, language):
         """i18n configuration for translation"""
@@ -137,24 +135,27 @@
             raise Exception('try to set pool on a closed session')
         if self.pool is None:
             # get pool first to avoid race-condition
-            self._threaddata.pool = self.repo._get_pool()
+            self._threaddata.pool = pool = self.repo._get_pool()
             try:
-                self._threaddata.pool.pool_set()
+                pool.pool_set()
             except:
                 self._threaddata.pool = None
-                self.repo._free_pool(self.pool)
+                self.repo._free_pool(pool)
                 raise
             self._threads_in_transaction.add(threading.currentThread())
         return self._threaddata.pool
 
     def reset_pool(self):
-        """the session has no longer using its pool, at least for some time"""
+        """the session is no longer using its pool, at least for some time"""
         # pool may be none if no operation has been done since last commit
         # or rollback
         if self.pool is not None and self.mode == 'read':
             # even in read mode, we must release the current transaction
             pool = self.pool
-            self._threads_in_transaction.remove(threading.currentThread())
+            try:
+                self._threads_in_transaction.remove(threading.currentThread())
+            except KeyError:
+                pass
             pool.pool_reset()
             self._threaddata.pool = None
             # free pool once everything is done to avoid race-condition
--- a/server/sources/extlite.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/server/sources/extlite.py	Wed Jul 08 10:45:31 2009 +0200
@@ -174,9 +174,7 @@
         if server.DEBUG:
             print self.uri, 'SOURCE RQL', union.as_string()
         args = self.sqladapter.merge_args(args, query_args)
-        cursor = session.pool[self.uri]
-        self.doexec(cursor, sql, args)
-        res = self.sqladapter.process_result(cursor)
+        res = self.sqladapter.process_result(self.doexec(session, sql, args))
         if server.DEBUG:
             print '------>', res
         return res
@@ -190,7 +188,7 @@
         """
         attrs = self.sqladapter.preprocess_entity(entity)
         sql = self.sqladapter.sqlgen.insert(SQL_PREFIX + str(entity.e_schema), attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def add_entity(self, session, entity):
         """add a new entity to the source"""
@@ -207,7 +205,7 @@
             attrs = self.sqladapter.preprocess_entity(entity)
         sql = self.sqladapter.sqlgen.update(SQL_PREFIX + str(entity.e_schema),
                                             attrs, [SQL_PREFIX + 'eid'])
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def update_entity(self, session, entity):
         """update an entity in the source"""
@@ -222,7 +220,7 @@
         """
         attrs = {SQL_PREFIX + 'eid': eid}
         sql = self.sqladapter.sqlgen.delete(SQL_PREFIX + etype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def local_add_relation(self, session, subject, rtype, object):
         """add a relation to the source
@@ -233,7 +231,7 @@
         """
         attrs = {'eid_from': subject, 'eid_to': object}
         sql = self.sqladapter.sqlgen.insert('%s_relation' % rtype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def add_relation(self, session, subject, rtype, object):
         """add a relation to the source"""
@@ -252,21 +250,25 @@
         else:
             attrs = {'eid_from': subject, 'eid_to': object}
             sql = self.sqladapter.sqlgen.delete('%s_relation' % rtype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
-    def doexec(self, cursor, query, args=None):
+    def doexec(self, session, query, args=None):
         """Execute a query.
         it's a function just so that it shows up in profiling
         """
-        #t1 = time()
         if server.DEBUG:
             print 'exec', query, args
-        #import sys
-        #sys.stdout.flush()
-        # str(query) to avoid error if it's an unicode string
+        cursor = session.pool[self.uri]
         try:
+            # str(query) to avoid error if it's an unicode string
             cursor.execute(str(query), args)
         except Exception, ex:
             self.critical("sql: %r\n args: %s\ndbms message: %r",
                           query, args, ex.args[0])
+            try:
+                session.pool.connection(self.uri).rollback()
+                self.critical('transaction has been rollbacked')
+            except:
+                pass
             raise
+        return cursor
--- a/server/sources/native.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/server/sources/native.py	Wed Jul 08 10:45:31 2009 +0200
@@ -185,9 +185,7 @@
 
     def sqlexec(self, session, sql, args=None):
         """execute the query and return its result"""
-        cursor = session.pool[self.uri]
-        self.doexec(cursor, sql, args)
-        return self.process_result(cursor)
+        return self.process_result(self.doexec(session, sql, args))
 
     def init_creating(self):
         pool = self.repo._get_pool()
@@ -305,17 +303,15 @@
                 sql, query_args = self._rql_sqlgen.generate(union, args, varmap)
                 self._cache[cachekey] = sql, query_args
         args = self.merge_args(args, query_args)
-        cursor = session.pool[self.uri]
         assert isinstance(sql, basestring), repr(sql)
         try:
-            self.doexec(cursor, sql, args)
+            cursor = self.doexec(session, sql, args)
         except (self.dbapi_module.OperationalError,
                 self.dbapi_module.InterfaceError):
             # FIXME: better detection of deconnection pb
             self.info("request failed '%s' ... retry with a new cursor", sql)
             session.pool.reconnect(self)
-            cursor = session.pool[self.uri]
-            self.doexec(cursor, sql, args)
+            cursor = self.doexec(session, sql, args)
         res = self.process_result(cursor)
         if server.DEBUG:
             print '------>', res
@@ -337,8 +333,7 @@
             # generate sql queries if we are able to do so
             sql, query_args = self._rql_sqlgen.generate(union, args, varmap)
             query = 'INSERT INTO %s %s' % (table, sql.encode(self.encoding))
-            self.doexec(session.pool[self.uri], query,
-                        self.merge_args(args, query_args))
+            self.doexec(session, query, self.merge_args(args, query_args))
         else:
             super(NativeSQLSource, self).flying_insert(table, session, union,
                                                        args, varmap)
@@ -358,15 +353,14 @@
                     cell = self.binary(cell.getvalue())
                 kwargs[str(index)] = cell
             kwargs_list.append(kwargs)
-        self.doexecmany(session.pool[self.uri], query, kwargs_list)
+        self.doexecmany(session, query, kwargs_list)
 
     def clean_temp_data(self, session, temptables):
         """remove temporary data, usually associated to temporary tables"""
         if temptables:
-            cursor = session.pool[self.uri]
             for table in temptables:
                 try:
-                    self.doexec(cursor,'DROP TABLE %s' % table)
+                    self.doexec(session,'DROP TABLE %s' % table)
                 except:
                     pass
                 try:
@@ -378,25 +372,25 @@
         """add a new entity to the source"""
         attrs = self.preprocess_entity(entity)
         sql = self.sqlgen.insert(SQL_PREFIX + str(entity.e_schema), attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def update_entity(self, session, entity):
         """replace an entity in the source"""
         attrs = self.preprocess_entity(entity)
         sql = self.sqlgen.update(SQL_PREFIX + str(entity.e_schema), attrs, [SQL_PREFIX + 'eid'])
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def delete_entity(self, session, etype, eid):
         """delete an entity from the source"""
         attrs = {SQL_PREFIX + 'eid': eid}
         sql = self.sqlgen.delete(SQL_PREFIX + etype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def add_relation(self, session, subject, rtype, object):
         """add a relation to the source"""
         attrs = {'eid_from': subject, 'eid_to': object}
         sql = self.sqlgen.insert('%s_relation' % rtype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
     def delete_relation(self, session, subject, rtype, object):
         """delete a relation from the source"""
@@ -410,39 +404,47 @@
         else:
             attrs = {'eid_from': subject, 'eid_to': object}
             sql = self.sqlgen.delete('%s_relation' % rtype, attrs)
-        self.doexec(session.pool[self.uri], sql, attrs)
+        self.doexec(session, sql, attrs)
 
-    def doexec(self, cursor, query, args=None):
+    def doexec(self, session, query, args=None):
         """Execute a query.
         it's a function just so that it shows up in profiling
         """
-        #t1 = time()
         if server.DEBUG:
             print 'exec', query, args
-        #import sys
-        #sys.stdout.flush()
-        # str(query) to avoid error if it's an unicode string
+        cursor = session.pool[self.uri]
         try:
+            # str(query) to avoid error if it's an unicode string
             cursor.execute(str(query), args)
         except Exception, ex:
             self.critical("sql: %r\n args: %s\ndbms message: %r",
                           query, args, ex.args[0])
+            try:
+                session.pool.connection(self.uri).rollback()
+                self.critical('transaction has been rollbacked')
+            except:
+                pass
             raise
+        return cursor
 
-    def doexecmany(self, cursor, query, args):
+    def doexecmany(self, session, query, args):
         """Execute a query.
         it's a function just so that it shows up in profiling
         """
-        #t1 = time()
         if server.DEBUG:
             print 'execmany', query, 'with', len(args), 'arguments'
-        #import sys
-        #sys.stdout.flush()
-        # str(query) to avoid error if it's an unicode string
+        cursor = session.pool[self.uri]
         try:
+            # str(query) to avoid error if it's an unicode string
             cursor.executemany(str(query), args)
-        except:
-            self.critical("sql many: %r\n args: %s", query, args)
+        except Exception, ex:
+            self.critical("sql many: %r\n args: %s\ndbms message: %r",
+                          query, args, ex.args[0])
+            try:
+                session.pool.connection(self.uri).rollback()
+                self.critical('transaction has been rollbacked')
+            except:
+                pass
             raise
 
     # short cut to method requiring advanced db helper usage ##################
@@ -498,14 +500,13 @@
         # running with an ldap source, and table will be deleted manually any way
         # on commit
         sql = self.dbhelper.sql_temporary_table(table, schema, False)
-        self.doexec(session.pool[self.uri], sql)
+        self.doexec(session, sql)
 
     def create_eid(self, session):
         self._eid_creation_lock.acquire()
         try:
-            cursor = session.pool[self.uri]
             for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
-                self.doexec(cursor, sql)
+                cursor = self.doexec(session, sql)
             return cursor.fetchone()[0]
         finally:
             self._eid_creation_lock.release()
--- a/view.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/view.py	Wed Jul 08 10:45:31 2009 +0200
@@ -12,7 +12,7 @@
 from cStringIO import StringIO
 
 from logilab.common.deprecation import obsolete
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import NotAnEntity
 from cubicweb.selectors import yes, non_final_entity, nonempty_rset, none_rset
@@ -219,7 +219,7 @@
 
     def wdata(self, data):
         """simple helper that escapes `data` and writes into `self.w`"""
-        self.w(html_escape(data))
+        self.w(xml_escape(data))
 
     def html_headers(self):
         """return a list of html headers (eg something to be inserted between
@@ -440,10 +440,10 @@
             def cb(*args):
                 _cb(*args)
         cbname = self.req.register_onetime_callback(cb, *args)
-        return self.build_js(cbname, html_escape(msg or ''))
+        return self.build_js(cbname, xml_escape(msg or ''))
 
     def build_update_js_call(self, cbname, msg):
-        rql = html_escape(self.rset.printable_rql())
+        rql = xml_escape(self.rset.printable_rql())
         return "javascript:userCallbackThenUpdateUI('%s', '%s', '%s', '%s', '%s', '%s')" % (
             cbname, self.id, rql, msg, self.__registry__, self.div_id())
 
--- a/vregistry.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/vregistry.py	Wed Jul 08 10:45:31 2009 +0200
@@ -1,10 +1,10 @@
 """
-* the vregistry handle various type of objects interacting
-  together. The vregistry handle registration of dynamically loaded
-  objects and provide a convenient api access to those objects
+* the vregistry handles various types of objects interacting
+  together. The vregistry handles registration of dynamically loaded
+  objects and provides a convenient api to access those objects
   according to a context
 
-* to interact with the vregistry, object should inherit from the
+* to interact with the vregistry, objects should inherit from the
   VObject abstract class
 
 * the selection procedure has been generalized by delegating to a
@@ -188,9 +188,6 @@
 
     # methods for explicit (un)registration ###################################
 
-#     def clear(self, key):
-#         regname, oid = key.split('.')
-#         self[regname].pop(oid, None)
     def register_all(self, objects, modname, butclasses=()):
         for obj in objects:
             try:
--- a/web/box.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/box.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import Unauthorized, role as get_role, target as get_target
 from cubicweb.selectors import (one_line_rset,  primary_view,
@@ -74,7 +74,7 @@
         .format_actions method
         """
         if escape:
-            title = html_escape(title)
+            title = xml_escape(title)
         return self.box_action(self._action(title, path, **kwargs))
 
     def _action(self, title, path, **kwargs):
--- a/web/component.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/component.py	Wed Jul 08 10:45:31 2009 +0200
@@ -9,7 +9,7 @@
 _ = unicode
 
 from logilab.common.deprecation import class_renamed
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import role
 from cubicweb.utils import merge_dicts
@@ -117,7 +117,7 @@
     def page_link(self, path, params, start, stop, content):
         url = self.build_url(path, **merge_dicts(params, {self.start_param : start,
                                                           self.stop_param : stop,}))
-        url = html_escape(url)
+        url = xml_escape(url)
         if start == self.starting_from:
             return self.selected_page_link_templ % (url, content, content)
         return self.page_link_templ % (url, content, content)
@@ -130,7 +130,7 @@
         stop = start + self.page_size - 1
         url = self.build_url(**merge_dicts(params, {self.start_param : start,
                                                     self.stop_param : stop,}))
-        url = html_escape(url)
+        url = xml_escape(url)
         return self.previous_page_link_templ % (url, title, content)
 
     def next_link(self, params, content='&gt;&gt;', title=_('next_results')):
@@ -140,7 +140,7 @@
         stop = start + self.page_size - 1
         url = self.build_url(**merge_dicts(params, {self.start_param : start,
                                                     self.stop_param : stop,}))
-        url = html_escape(url)
+        url = xml_escape(url)
         return self.next_page_link_templ % (url, title, content)
 
 
--- a/web/controller.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/controller.py	Wed Jul 08 10:45:31 2009 +0200
@@ -182,11 +182,9 @@
         elif '__redirectpath' in self.req.form:
             # if redirect path was explicitly specified in the form, use it
             path = self.req.form['__redirectpath']
-            if self._edited_entity:
-                msg = newparams.get('__message', '')
-                msg += ' (<a href="%s">%s</a>)' % (
-                    self._edited_entity.absolute_url(),
-                    self.req._('click here to see created entity'))
+            if self._edited_entity and path != self._edited_entity.rest_path():
+                # XXX may be here on modification? if yes the message should be
+                # modified where __createdpath is detected (cw.web.request)
                 newparams['__createdpath'] = self._edited_entity.rest_path()
         elif self._after_deletion_path:
             # else it should have been set during form processing
--- a/web/facet.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/facet.py	Wed Jul 08 10:45:31 2009 +0200
@@ -12,7 +12,7 @@
 from copy import deepcopy
 from datetime import date, datetime, timedelta
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from logilab.common.graph import has_path
 from logilab.common.decorators import cached
@@ -21,6 +21,7 @@
 from rql import parse, nodes
 
 from cubicweb import Unauthorized, typed_eid
+from cubicweb.schema import display_name
 from cubicweb.utils import datetime2ticks, make_uid, ustrftime
 from cubicweb.selectors import match_context_prop, partial_relation_possible
 from cubicweb.appobject import AppRsetObject
@@ -70,7 +71,7 @@
 def filter_hiddens(w, **kwargs):
     for key, val in kwargs.items():
         w(u'<input type="hidden" name="%s" value="%s" />' % (
-            key, html_escape(val)))
+            key, xml_escape(val)))
 
 
 def _may_be_removed(rel, schema, mainvar):
@@ -586,11 +587,11 @@
         self.items.append(item)
 
     def _render(self):
-        title = html_escape(self.facet.title)
-        facetid = html_escape(self.facet.id)
+        title = xml_escape(self.facet.title)
+        facetid = xml_escape(self.facet.id)
         self.w(u'<div id="%s" class="facet">\n' % facetid)
         self.w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
-               (html_escape(facetid), title))
+               (xml_escape(facetid), title))
         if self.facet.support_and():
             _ = self.facet.req._
             self.w(u'''<select name="%s" class="radio facetOperator" title="%s">
@@ -616,8 +617,8 @@
         self.value = None
 
     def _render(self):
-        title = html_escape(self.facet.title)
-        facetid = html_escape(self.facet.id)
+        title = xml_escape(self.facet.title)
+        facetid = xml_escape(self.facet.id)
         self.w(u'<div id="%s" class="facet">\n' % facetid)
         self.w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
                (facetid, title))
@@ -660,7 +661,7 @@
         facet.req.add_js('ui.slider.js')
         facet.req.add_css('ui.all.css')
         sliderid = make_uid('the slider')
-        facetid = html_escape(self.facet.id)
+        facetid = xml_escape(self.facet.id)
         facet.req.html_headers.add_onload(self.onload % {
             'sliderid': sliderid,
             'facetid': facetid,
@@ -668,7 +669,7 @@
             'maxvalue': self.maxvalue,
             'formatter': self.formatter,
             })
-        title = html_escape(self.facet.title)
+        title = xml_escape(self.facet.title)
         self.w(u'<div id="%s" class="facet">\n' % facetid)
         self.w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
                (facetid, title))
@@ -720,9 +721,9 @@
             imgsrc = self.req.datadir_url + self.unselected_img
             imgalt = self.req._('not selected')
         self.w(u'<div class="facetValue facetCheckBox%s" cubicweb:value="%s">\n'
-               % (cssclass, html_escape(unicode(self.value))))
+               % (cssclass, xml_escape(unicode(self.value))))
         self.w(u'<img src="%s" alt="%s"/>&nbsp;' % (imgsrc, imgalt))
-        self.w(u'<a href="javascript: {}">%s</a>' % html_escape(self.label))
+        self.w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
         self.w(u'</div>')
 
 class CheckBoxFacetWidget(HTMLWidget):
@@ -736,8 +737,8 @@
         self.selected = selected
 
     def _render(self):
-        title = html_escape(self.facet.title)
-        facetid = html_escape(self.facet.id)
+        title = xml_escape(self.facet.title)
+        facetid = xml_escape(self.facet.id)
         self.w(u'<div id="%s" class="facet">\n' % facetid)
         if self.selected:
             cssclass = ' facetValueSelected'
@@ -748,7 +749,7 @@
             imgsrc = self.req.datadir_url + self.unselected_img
             imgalt = self.req._('not selected')
         self.w(u'<div class="facetValue facetCheckBox%s" cubicweb:value="%s">\n'
-               % (cssclass, html_escape(unicode(self.value))))
+               % (cssclass, xml_escape(unicode(self.value))))
         self.w(u'<div class="facetCheckBoxWidget">')
         self.w(u'<img src="%s" alt="%s" cubicweb:unselimg="true" />&nbsp;' % (imgsrc, imgalt))
         self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid, title))
--- a/web/formfields.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/formfields.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 from warnings import warn
 from datetime import datetime
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 from yams.constraints import SizeConstraint, StaticVocabularyConstraint
 
 from cubicweb.schema import FormatConstraint
@@ -300,9 +300,9 @@
         if self.format_field or self.encoding_field:
             divid = '%s-advanced' % form.context[self]['name']
             wdgs.append(u'<a href="%s" title="%s"><img src="%s" alt="%s"/></a>' %
-                        (html_escape(uilib.toggle_action(divid)),
+                        (xml_escape(uilib.toggle_action(divid)),
                          form.req._('show advanced fields'),
-                         html_escape(form.req.build_url('data/puce_down.png')),
+                         xml_escape(form.req.build_url('data/puce_down.png')),
                          form.req._('show advanced fields')))
             wdgs.append(u'<div id="%s" class="hidden">' % divid)
             if self.format_field:
--- a/web/htmlwidgets.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/htmlwidgets.py	Wed Jul 08 10:45:31 2009 +0200
@@ -9,7 +9,7 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.utils import UStringIO
 from cubicweb.common.uilib import toggle_action
@@ -81,7 +81,7 @@
             self.w(u'<div class="%s">' % self._class)
         if self.title:
             if self.escape:
-                title = '<span>%s</span>' % html_escape(self.title)
+                title = '<span>%s</span>' % xml_escape(self.title)
             else:
                 title = '<span>%s</span>' % self.title
             self.w(u'<div class="%s">%s</div>' % (self.title_class, title))
@@ -204,7 +204,7 @@
     def __init__(self, href, label, _class='', title='', ident='', escape=False):
         self.href = href
         if escape:
-            self.label = html_escape(label)
+            self.label = xml_escape(label)
         else:
             self.label = label
         self._class = _class or ''
@@ -213,7 +213,7 @@
 
     def _render(self):
         link = u'<a href="%s" title="%s">%s</a>' % (
-            html_escape(self.href), html_escape(self.title), self.label)
+            xml_escape(self.href), xml_escape(self.title), self.label)
         if self.ident:
             self.w(u'<li id="%s" class="%s">%s</li>\n' % (self.ident, self._class, link))
         else:
--- a/web/request.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/request.py	Wed Jul 08 10:45:31 2009 +0200
@@ -20,7 +20,7 @@
 from logilab.common.decorators import cached
 from logilab.common.deprecation import obsolete
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.dbapi import DBAPIRequest
 from cubicweb.common.mail import header
@@ -153,7 +153,8 @@
             else:
                 self.form[k] = v
         # special key for created entity, added in controller's reset method
-        if '__createdpath' in params:
+        # if no message set, we don't want this neither
+        if '__createdpath' in params and self.message:
             self.message += ' (<a href="%s">%s</a>)' % (
                 self.build_url(params.pop('__createdpath')),
                 self._('click here to see created entity'))
@@ -505,7 +506,7 @@
         url = self.build_url('view', rql=rql, vid=vid, __notemplate=1,
                              **extraparams)
         return "javascript: loadxhtml('%s', '%s', '%s')" % (
-            nodeid, html_escape(url), replacemode)
+            nodeid, xml_escape(url), replacemode)
 
     # urls/path management ####################################################
 
--- a/web/views/basecomponents.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/basecomponents.py	Wed Jul 08 10:45:31 2009 +0200
@@ -11,11 +11,12 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
+from logilab.mtconverter import xml_escape
 from rql import parse
 
 from cubicweb.selectors import yes, two_etypes_rset, match_form_params
 from cubicweb.schema import display_name
-from cubicweb.common.uilib import html_escape, toggle_action
+from cubicweb.common.uilib import toggle_action
 from cubicweb.web import component
 from cubicweb.web.htmlwidgets import (MenuWidget, PopupBoxMenu, BoxSeparator,
                                       BoxLink)
@@ -47,7 +48,7 @@
 <input type="submit" value="" class="rqlsubmit" tabindex="%s" />
 </fieldset>
 ''' % (not self.propval('visible') and 'hidden' or '',
-       self.build_url('view'), html_escape(rql), req._('full text or RQL query'), req.next_tabindex(),
+       self.build_url('view'), xml_escape(rql), req._('full text or RQL query'), req.next_tabindex(),
         req.next_tabindex()))
         if self.req.search_state[0] != 'normal':
             self.w(u'<input type="hidden" name="__mode" value="%s"/>'
@@ -202,7 +203,7 @@
                 url = self.build_url(rql=newrql, __restrrql=restrrql,
                                      __restrtype=etype, __restrtypes=','.join(restrtypes))
                 html.append(u'<span><a href="%s">%s</a></span>' % (
-                        html_escape(url), elabel))
+                        xml_escape(url), elabel))
                 rqlst.recover()
         if on_etype:
             url = self.build_url(rql=restrrql)
--- a/web/views/basecontrollers.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/basecontrollers.py	Wed Jul 08 10:45:31 2009 +0200
@@ -15,7 +15,7 @@
 import simplejson
 
 from logilab.common.decorators import cached
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import NoSelectableObject, ValidationError, ObjectNotFound, typed_eid
 from cubicweb.utils import strptime
@@ -411,7 +411,7 @@
             if rset:
                 output = self.view(vid, rset)
                 if vid == 'textoutofcontext':
-                    output = html_escape(output)
+                    output = xml_escape(output)
             else:
                 output = default
             return (success, args, output)
--- a/web/views/baseforms.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/baseforms.py	Wed Jul 08 10:45:31 2009 +0200
@@ -12,7 +12,7 @@
 
 from simplejson import dumps
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 from logilab.common.decorators import cached
 
 from cubicweb.selectors import (specified_etype_implements, accepts_etype_compat,
@@ -148,7 +148,7 @@
         output = []
         for name, value, iid in self._hiddens:
             if isinstance(value, basestring):
-                value = html_escape(value)
+                value = xml_escape(value)
             if iid:
                 output.append(u'<input id="%s" type="hidden" name="%s" value="%s" />'
                               % (iid, name, value))
@@ -249,14 +249,14 @@
                 w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
                   (_('cancel this insert'), row[2]))
                 w(u'<a id="a%s" class="editionPending" href="%s">%s</a>'
-                  % (row[1], row[4], html_escape(row[5])))
+                  % (row[1], row[4], xml_escape(row[5])))
                 w(u'</td>')
                 w(u'</tr>')
         w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
         w(u'<th class="labelCol">')
         w(u'<span>%s</span>' % _('add relation'))
         w(u'<select id="relationSelector_%s" tabindex="%s" onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
-          % (eid, req.next_tabindex(), html_escape(dumps(eid))))
+          % (eid, req.next_tabindex(), xml_escape(dumps(eid))))
         w(u'<option value="">%s</option>' % _('select a relation'))
         for i18nrtype, rschema, target in srels_by_cat:
             # more entities to link to
@@ -551,10 +551,10 @@
         ctx = {'action' : self.build_url('edit'),
                'error': self.error_message(),
                'progress': _('validating...'),
-               'url': html_escape(req.url()),
+               'url': xml_escape(req.url()),
                'formid': self.id,
-               'redirectvid': html_escape(form.get('__redirectvid', 'list')),
-               'redirectrql': html_escape(form.get('__redirectrql', self.rset.printable_rql())),
+               'redirectvid': xml_escape(form.get('__redirectvid', 'list')),
+               'redirectrql': xml_escape(form.get('__redirectrql', self.rset.printable_rql())),
                'attrheaders': u'\n'.join(attrheaders),
                'lines': u'\n'.join(self.edit_form(ent) for ent in self.rset.entities()),
                'okvalue': _('button_ok').capitalize(),
@@ -583,7 +583,7 @@
         wdg = entity.get_widget
         wdgfactories = [wdg(rschema, x) for rschema, _, x in entity.relations_by_category('primary', 'add')
                         if rschema.type != 'eid'] # XXX both (add, delete)
-        seid = html_escape(dumps(eid))
+        seid = xml_escape(dumps(eid))
         for wobj in wdgfactories:
             if isinstance(wobj, ComboBoxWidget):
                 wobj.attrs['onchange'] = "setCheckboxesState2('eid', %s, 'checked')" % seid
--- a/web/views/basetemplates.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/basetemplates.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.vregistry import objectify_selector
 from cubicweb.selectors import match_kwargs
@@ -31,14 +31,14 @@
     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
         w = self.whead
         # explictly close the <base> tag to avoid IE 6 bugs while browsing DOM
-        w(u'<base href="%s"></base>' % html_escape(self.req.base_url()))
+        w(u'<base href="%s"></base>' % xml_escape(self.req.base_url()))
         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
           % (content_type, self.req.encoding))
         w(NOINDEX)
         w(NOFOLLOW)
         w(u'\n'.join(additional_headers) + u'\n')
         self.wview('htmlheader', rset=self.rset)
-        w(u'<title>%s</title>\n' % html_escape(page_title))
+        w(u'<title>%s</title>\n' % xml_escape(page_title))
 
 
 class LogInTemplate(LogInOutTemplate):
@@ -60,7 +60,7 @@
         if self.config['anonymous-user']:
             indexurl = self.build_url('view', vid='index', __message=msg)
             w(u'<p><a href="%s">%s</a><p>' % (
-                html_escape(indexurl),
+                xml_escape(indexurl),
                 self.req._('go back to the index page')))
 
 @objectify_selector
@@ -110,7 +110,7 @@
         w(u'<div id="pageContent">\n')
         vtitle = self.req.form.get('vtitle')
         if vtitle:
-            w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle))
+            w(u'<h1 class="vtitle">%s</h1>\n' % xml_escape(vtitle))
         # display entity type restriction component
         etypefilter = self.vreg.select_component('etypenavigation',
                                                  self.req, self.rset)
@@ -137,13 +137,13 @@
         w = self.whead
         lang = self.req.lang
         self.write_doctype()
-        w(u'<base href="%s" />' % html_escape(self.req.base_url()))
+        w(u'<base href="%s" />' % xml_escape(self.req.base_url()))
         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
           % (content_type, self.req.encoding))
         w(u'\n'.join(additional_headers) + u'\n')
         self.wview('htmlheader', rset=self.rset)
         if page_title:
-            w(u'<title>%s</title>\n' % html_escape(page_title))
+            w(u'<title>%s</title>\n' % xml_escape(page_title))
 
     def template_body_header(self, view):
         w = self.w
@@ -210,7 +210,7 @@
           % (content_type, self.req.encoding))
         w(u'\n'.join(additional_headers))
         self.wview('htmlheader', rset=self.rset)
-        w(u'<title>%s</title>\n' % html_escape(page_title))
+        w(u'<title>%s</title>\n' % xml_escape(page_title))
         self.w(u'<body>\n')
 
     def template_footer(self, view=None):
@@ -232,7 +232,7 @@
         whead(u'\n'.join(additional_headers) + u'\n')
         self.wview('htmlheader', rset=self.rset)
         w = self.w
-        w(u'<title>%s</title>\n' % html_escape(page_title))
+        w(u'<title>%s</title>\n' % xml_escape(page_title))
         w(u'<body>\n')
         w(u'<div id="page">')
         w(u'<table width="100%" height="100%" border="0"><tr>\n')
@@ -250,7 +250,7 @@
         w(u'<div id="pageContent">\n')
         vtitle = self.req.form.get('vtitle')
         if vtitle:
-            w(u'<h1 class="vtitle">%s</h1>' % html_escape(vtitle))
+            w(u'<h1 class="vtitle">%s</h1>' % xml_escape(vtitle))
 
     def topleft_header(self):
         self.w(u'<table id="header"><tr>\n')
@@ -296,7 +296,7 @@
         if urlgetter is not None:
             url = urlgetter.feed_url()
             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
-                       %  html_escape(url))
+                       %  xml_escape(url))
 
     def pageid(self):
         req = self.req
@@ -452,7 +452,7 @@
     def login_form(self, id):
         _ = self.req._
         self.w(u'<form method="post" action="%s" id="login_form">\n'
-               % html_escape(login_form_url(self.config, self.req)))
+               % xml_escape(login_form_url(self.config, self.req)))
         self.w(u'<table>\n')
         self.w(u'<tr>\n')
         msg = (self.config['allow-email-login'] and _('login or email')) or _('login')
--- a/web/views/baseviews.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/baseviews.py	Wed Jul 08 10:45:31 2009 +0200
@@ -17,7 +17,7 @@
 
 from rql import nodes
 
-from logilab.mtconverter import TransformError, html_escape, xml_escape
+from logilab.mtconverter import TransformError, xml_escape, xml_escape
 
 from cubicweb import NoSelectableObject
 from cubicweb.selectors import yes, empty_rset
@@ -121,8 +121,8 @@
         """the one line view for an entity: linked text view
         """
         entity = self.entity(row, col)
-        self.w(u'<a href="%s">' % html_escape(entity.absolute_url()))
-        self.w(html_escape(self.view('text', self.rset, row=row, col=col)))
+        self.w(u'<a href="%s">' % xml_escape(entity.absolute_url()))
+        self.w(xml_escape(self.view('text', self.rset, row=row, col=col)))
         self.w(u'</a>')
 
 
@@ -205,8 +205,8 @@
         entity = self.entity(row, col)
         desc = cut(entity.dc_description(), 50)
         self.w(u'<a href="%s" title="%s">' % (
-            html_escape(entity.absolute_url()), html_escape(desc)))
-        self.w(html_escape(self.view('textincontext', self.rset,
+            xml_escape(entity.absolute_url()), xml_escape(desc)))
+        self.w(xml_escape(self.view('textincontext', self.rset,
                                      row=row, col=col)))
         self.w(u'</a>')
 
@@ -218,8 +218,8 @@
         entity = self.entity(row, col)
         desc = cut(entity.dc_description(), 50)
         self.w(u'<a href="%s" title="%s">' % (
-            html_escape(entity.absolute_url()), html_escape(desc)))
-        self.w(html_escape(self.view('textoutofcontext', self.rset,
+            xml_escape(entity.absolute_url()), xml_escape(desc)))
+        self.w(xml_escape(self.view('textoutofcontext', self.rset,
                                      row=row, col=col)))
         self.w(u'</a>')
 
--- a/web/views/bookmark.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/bookmark.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import Unauthorized
 from cubicweb.selectors import implements
@@ -35,12 +35,12 @@
         entity = self.complete_entity(row, col)
         self.w(u'&nbsp;')
         self.w(u"<span class='title'><b>")
-        self.w(u"%s : %s" % (self.req._('Bookmark'), html_escape(entity.title)))
+        self.w(u"%s : %s" % (self.req._('Bookmark'), xml_escape(entity.title)))
         self.w(u"</b></span>")
         self.w(u'<br/><br/><div class="content"><a href="%s">' % (
-            html_escape(entity.actual_url())))
+            xml_escape(entity.actual_url())))
         self.w(u'</a>')
-        self.w(u'<p>%s%s</p>' % (self.req._('Used by:'), ', '.join(html_escape(u.name())
+        self.w(u'<p>%s%s</p>' % (self.req._('Used by:'), ', '.join(xml_escape(u.name())
                                                                    for u in entity.bookmarked_by)))
         self.w(u'</div>')
 
@@ -75,8 +75,8 @@
         else:
             dlink = None
         for bookmark in rset.entities():
-            label = '<a href="%s">%s</a>' % (html_escape(bookmark.action_url()),
-                                             html_escape(bookmark.title))
+            label = '<a href="%s">%s</a>' % (xml_escape(bookmark.action_url()),
+                                             xml_escape(bookmark.title))
             if candelete:
                 dlink = u'[<a href="javascript:removeBookmark(%s)" title="%s">-</a>]' % (
                     bookmark.eid, _('delete this bookmark'))
--- a/web/views/boxes.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/boxes.py	Wed Jul 08 10:45:31 2009 +0200
@@ -16,7 +16,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import match_user_groups, non_final_entity
 from cubicweb.view import EntityView
@@ -191,7 +191,7 @@
         else:
             rql = ''
         form = self.formdef % (req.build_url('view'), req.next_tabindex(),
-                               html_escape(rql), req.next_tabindex())
+                               xml_escape(rql), req.next_tabindex())
         title = u"""<span onclick="javascript: toggleVisibility('rqlinput')">%s</span>""" % req._(self.title)
         box = BoxWidget(title, self.id, _class="searchBoxFrame", islist=False, escape=False)
         box.append(BoxHtml(form))
--- a/web/views/calendar.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/calendar.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 
 from datetime import datetime, date, timedelta
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.interfaces import ICalendarable
 from cubicweb.selectors import implements
@@ -82,7 +82,7 @@
         for i in range(len(self.rset.rows)):
             task = self.complete_entity(i)
             self.w(u'<div class="vevent">')
-            self.w(u'<h3 class="summary">%s</h3>' % html_escape(task.dc_title()))
+            self.w(u'<h3 class="summary">%s</h3>' % xml_escape(task.dc_title()))
             self.w(u'<div class="description">%s</div>'
                    % task.dc_description(format='text/html'))
             if task.start:
@@ -244,8 +244,8 @@
         prevlink, nextlink = self._prevnext_links(curdate)  # XXX
         self.w(u'<tr><th><a href="%s">&lt;&lt;</a></th><th colspan="5">%s %s</th>'
                u'<th><a href="%s">&gt;&gt;</a></th></tr>' %
-               (html_escape(prevlink), self.req._(curdate.strftime('%B').lower()),
-                curdate.year, html_escape(nextlink)))
+               (xml_escape(prevlink), self.req._(curdate.strftime('%B').lower()),
+                curdate.year, xml_escape(nextlink)))
 
         # output header
         self.w(u'<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>' %
@@ -292,7 +292,7 @@
                                  __redirectparams=self.req.build_url_params(year=curdate.year, month=curmonth),
                                  __redirectvid=self.id
                                  )
-            self.w(u'<div class="cmd"><a href="%s">%s</a></div>' % (html_escape(url), self.req._(u'add')))
+            self.w(u'<div class="cmd"><a href="%s">%s</a></div>' % (xml_escape(url), self.req._(u'add')))
             self.w(u'&nbsp;')
         self.w(u'</div>')
         self.w(u'<div class="cellContent">')
@@ -307,7 +307,7 @@
                                         __redirectvid=self.id
                                         )
 
-                self.w(u'<div class="tooltip" ondblclick="stopPropagation(event); window.location.assign(\'%s\'); return false;">' % html_escape(url))
+                self.w(u'<div class="tooltip" ondblclick="stopPropagation(event); window.location.assign(\'%s\'); return false;">' % xml_escape(url))
                 task.view('tooltip', w=self.w )
                 self.w(u'</div>')
             else:
@@ -388,9 +388,9 @@
         self.w(u'<tr><th class="transparent"></th>')
         self.w(u'<th><a href="%s">&lt;&lt;</a></th><th colspan="5">%s %s %s</th>'
                u'<th><a href="%s">&gt;&gt;</a></th></tr>' %
-               (html_escape(prevlink), first_day_of_week.year,
+               (xml_escape(prevlink), first_day_of_week.year,
                 self.req._(u'week'), first_day_of_week.isocalendar()[1],
-                html_escape(nextlink)))
+                xml_escape(nextlink)))
 
         # output header
         self.w(u'<tr>')
@@ -429,7 +429,7 @@
                                      __redirectvid=self.id
                                      )
                 extra = ' ondblclick="addCalendarItem(event, hmin=8, hmax=20, year=%s, month=%s, day=%s, duration=2, baseurl=\'%s\')"' % (
-                    wdate.year, wdate.month, wdate.day, html_escape(url))
+                    wdate.year, wdate.month, wdate.day, xml_escape(url))
             else:
                 extra = ""
             self.w(u'<div class="columndiv"%s>'% extra)
@@ -501,7 +501,7 @@
                                     __redirectvid=self.id
                                  )
 
-            self.w(u'<div class="tooltip" ondblclick="stopPropagation(event); window.location.assign(\'%s\'); return false;">' % html_escape(url))
+            self.w(u'<div class="tooltip" ondblclick="stopPropagation(event); window.location.assign(\'%s\'); return false;">' % xml_escape(url))
             task.view('tooltip', w=self.w)
             self.w(u'</div>')
             if task.start is None:
--- a/web/views/csvexport.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/csvexport.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,6 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
+from cubicweb.schema import display_name
 from cubicweb.common.uilib import UnicodeCSVWriter
 from cubicweb.view import EntityView, AnyRsetView
 
--- a/web/views/cwproperties.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/cwproperties.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from logilab.common.decorators import cached
 
@@ -154,7 +154,7 @@
                 docmsgid = '%s_%s_description' % (group, oid)
                 doc = _(docmsgid)
                 if doc != docmsgid:
-                    w(u'<div class="helper">%s</div>' % html_escape(doc).capitalize())
+                    w(u'<div class="helper">%s</div>' % xml_escape(doc).capitalize())
                 w(u'</div>')
                 w(u'<fieldset id="field_%(oid)s_%(group)s" class="%(group)s preferences hidden">'
                   % {'oid':oid, 'group':group})
--- a/web/views/cwuser.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/cwuser.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import one_line_rset, implements, match_user_groups
 from cubicweb.view import EntityView
@@ -52,14 +52,14 @@
                       <foaf:primaryTopic rdf:resource="%s"/>
                    </foaf:PersonalProfileDocument>''' % (entity.absolute_url(), entity.absolute_url()))
         self.w(u'<foaf:Person rdf:ID="%s">\n' % entity.eid)
-        self.w(u'<foaf:name>%s</foaf:name>\n' % html_escape(entity.dc_long_title()))
+        self.w(u'<foaf:name>%s</foaf:name>\n' % xml_escape(entity.dc_long_title()))
         if entity.surname:
             self.w(u'<foaf:family_name>%s</foaf:family_name>\n'
-                   % html_escape(entity.surname))
+                   % xml_escape(entity.surname))
         if entity.firstname:
             self.w(u'<foaf:givenname>%s</foaf:givenname>\n'
-                   % html_escape(entity.firstname))
+                   % xml_escape(entity.firstname))
         emailaddr = entity.get_email()
         if emailaddr:
-            self.w(u'<foaf:mbox>%s</foaf:mbox>\n' % html_escape(emailaddr))
+            self.w(u'<foaf:mbox>%s</foaf:mbox>\n' % xml_escape(emailaddr))
         self.w(u'</foaf:Person>\n')
--- a/web/views/debug.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/debug.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 
 from time import strftime, localtime
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import none_rset, match_user_groups
 from cubicweb.view import StartupView
@@ -21,7 +21,7 @@
         w(u'<ul>')
         for key in sorted(dict):
             w(u'<li><span class="label">%s</span>: <span>%s</span></li>' % (
-                html_escape(str(key)), html_escape(repr(dict[key]))))
+                xml_escape(str(key)), xml_escape(repr(dict[key]))))
         w(u'</ul>')
 
 
@@ -38,7 +38,7 @@
         if sessions:
             w(u'<ul>')
             for sid, session in sessions:
-                w(u'<li>%s  (last usage: %s)<br/>' % (html_escape(str(session)),
+                w(u'<li>%s  (last usage: %s)<br/>' % (xml_escape(str(session)),
                                                       strftime('%Y-%m-%d %H:%M:%S',
                                                                localtime(session.timestamp))))
                 dict_to_html(w, session.data)
--- a/web/views/editforms.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/editforms.py	Wed Jul 08 10:45:31 2009 +0200
@@ -13,7 +13,7 @@
 
 from simplejson import dumps
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
                                 specified_etype_implements, yes)
@@ -38,7 +38,7 @@
     entities
     """
     js = u"javascript: togglePendingDelete('%s', %s);" % (
-        nodeid, html_escape(dumps(eid)))
+        nodeid, xml_escape(dumps(eid)))
     return u'[<a class="handle" href="%s" id="handle%s">%s</a>]' % (
         js, nodeid, label)
 
@@ -108,8 +108,8 @@
                 return
         else:
             rset = entity.related(rtype, role)
-            # XXX html_escape but that depends of the actual vid
-            value = html_escape(self.view(vid, rset, 'null') or default)
+            # XXX xml_escape but that depends of the actual vid
+            value = xml_escape(self.view(vid, rset, 'null') or default)
         # XXX consider local roles ?
         if role == 'subject'and not rschema.has_perm(self.req, 'add',
                                                     fromeid=entity.eid):
--- a/web/views/editviews.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/editviews.py	Wed Jul 08 10:45:31 2009 +0200
@@ -11,7 +11,7 @@
 from simplejson import dumps
 
 from logilab.common.decorators import cached
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import typed_eid
 from cubicweb.view import EntityView
@@ -64,10 +64,10 @@
         erset = entity.as_rset()
         if self.req.match_search_state(erset):
             self.w(u'<a href="%s" title="%s">%s</a>&nbsp;<a href="%s" title="%s">[...]</a>' % (
-                html_escape(linksearch_select_url(self.req, erset)),
+                xml_escape(linksearch_select_url(self.req, erset)),
                 self.req._('select this entity'),
-                html_escape(entity.view('textoutofcontext')),
-                html_escape(entity.absolute_url(vid='primary')),
+                xml_escape(entity.view('textoutofcontext')),
+                xml_escape(entity.absolute_url(vid='primary')),
                 self.req._('view detail for this entity')))
         else:
             entity.view('outofcontext', w=self.w)
@@ -111,7 +111,7 @@
   </select>
 </div>
 """ % (hidden and 'hidden' or '', divid, selectid,
-       html_escape(dumps(entity.eid)), is_cell and 'true' or 'null', relname,
+       xml_escape(dumps(entity.eid)), is_cell and 'true' or 'null', relname,
        '\n'.join(options))
 
     def _get_select_options(self, entity, rschema, target):
@@ -127,13 +127,13 @@
         for eview, reid in form.form_field_vocabulary(field, limit):
             if reid is None:
                 options.append('<option class="separator">-- %s --</option>'
-                               % html_escape(eview))
+                               % xml_escape(eview))
             else:
                 optionid = relation_id(eid, rtype, target, reid)
                 if optionid not in pending_inserts:
                     # prefix option's id with letters to make valid XHTML wise
                     options.append('<option id="id%s" value="%s">%s</option>' %
-                                   (optionid, reid, html_escape(eview)))
+                                   (optionid, reid, xml_escape(eview)))
         return options
 
     def _get_search_options(self, entity, rschema, target, targettypes):
@@ -146,7 +146,7 @@
                                  __mode=mode)
             options.append((eschema.display_name(self.req),
                             '<option value="%s">%s %s</option>' % (
-                html_escape(url), _('Search for'), eschema.display_name(self.req))))
+                xml_escape(url), _('Search for'), eschema.display_name(self.req))))
         return [o for l, o in sorted(options)]
 
     def _get_basket_options(self, entity, rschema, target, targettypes):
@@ -157,7 +157,7 @@
                                                             target, targettypes):
             optionid = relation_id(entity.eid, rtype, target, basketeid)
             options.append('<option id="%s" value="%s">%s %s</option>' % (
-                optionid, basketeid, _('link to each item in'), html_escape(basketname)))
+                optionid, basketeid, _('link to each item in'), xml_escape(basketname)))
         return options
 
     def _get_basket_links(self, ueid, target, targettypes):
--- a/web/views/emailaddress.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/emailaddress.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,8 +7,9 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
+from cubicweb.schema import display_name
 from cubicweb.selectors import implements
 from cubicweb.common import Unauthorized
 from cubicweb.web.views import baseviews, primary
@@ -79,9 +80,9 @@
         if entity.reverse_primary_email:
             self.w(u'<b>')
         if entity.alias:
-            self.w(u'%s &lt;' % html_escape(entity.alias))
-        self.w('<a href="%s">%s</a>' % (html_escape(entity.absolute_url()),
-                                        html_escape(entity.display_address())))
+            self.w(u'%s &lt;' % xml_escape(entity.alias))
+        self.w('<a href="%s">%s</a>' % (xml_escape(entity.absolute_url()),
+                                        xml_escape(entity.display_address())))
         if entity.alias:
             self.w(u'&gt;\n')
         if entity.reverse_primary_email:
@@ -108,8 +109,8 @@
             mailto = "mailto:%s <%s>" % (alias, entity.display_address())
         else:
             mailto = "mailto:%s" % entity.display_address()
-        self.w(u'<a href="%s">%s</a>' % (html_escape(mailto),
-                                         html_escape(entity.display_address())))
+        self.w(u'<a href="%s">%s</a>' % (xml_escape(mailto),
+                                         xml_escape(entity.display_address())))
         if entity.reverse_primary_email:
             self.w(u'</b>')
 
--- a/web/views/facets.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/facets.py	Wed Jul 08 10:45:31 2009 +0200
@@ -9,7 +9,7 @@
 
 from simplejson import dumps
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.vregistry import objectify_selector
 from cubicweb.selectors import (non_final_entity, two_lines_rset,
@@ -86,7 +86,7 @@
                 self.display_bookmark_link(rset)
             w = self.w
             w(u'<form method="post" id="%sForm" cubicweb:facetargs="%s" action="">'  % (
-                divid, html_escape(dumps([divid, vid, paginate, self.facetargs()]))))
+                divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()]))))
             w(u'<fieldset>')
             hiddens = {'facets': ','.join(wdg.facet.id for wdg in widgets),
                        'baserql': baserql}
@@ -111,8 +111,8 @@
             bk_add_url = self.build_url('add/Bookmark', path=bk_path, title=bk_title, __linkto=linkto)
             bk_base_url = self.build_url('add/Bookmark', title=bk_title, __linkto=linkto)
             bk_link = u'<a cubicweb:target="%s" id="facetBkLink" href="%s">%s</a>' % (
-                    html_escape(bk_base_url),
-                    html_escape(bk_add_url),
+                    xml_escape(bk_base_url),
+                    xml_escape(bk_add_url),
                     self.req._('bookmark this search'))
             self.w(self.bk_linkbox_template % bk_link)
 
--- a/web/views/formrenderers.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/formrenderers.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 
 from logilab.common import dictattr
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from simplejson import dumps
 
@@ -144,17 +144,17 @@
         else:
             action = form.action
         tag = ('<form action="%s" method="post" enctype="%s"' % (
-            html_escape(action or '#'), enctype))
+            xml_escape(action or '#'), enctype))
         if form.domid:
             tag += ' id="%s"' % form.domid
         if form.onsubmit:
-            tag += ' onsubmit="%s"' % html_escape(form.onsubmit % dictattr(form))
+            tag += ' onsubmit="%s"' % xml_escape(form.onsubmit % dictattr(form))
         if form.cssstyle:
-            tag += ' style="%s"' % html_escape(form.cssstyle)
+            tag += ' style="%s"' % xml_escape(form.cssstyle)
         if form.cssclass:
-            tag += ' class="%s"' % html_escape(form.cssclass)
+            tag += ' class="%s"' % xml_escape(form.cssclass)
         if form.cwtarget:
-            tag += ' cubicweb:target="%s"' % html_escape(form.cwtarget)
+            tag += ' cubicweb:target="%s"' % xml_escape(form.cwtarget)
         return tag + '>'
 
     def display_field(self, form, field):
@@ -298,7 +298,7 @@
             entity = form.edited_entity
             values = form.form_previous_values
             qeid = eid_param('eid', entity.eid)
-            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % html_escape(dumps(entity.eid))
+            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % xml_escape(dumps(entity.eid))
             w(u'<tr class="%s">' % (entity.row % 2 and u'even' or u'odd'))
             # XXX turn this into a widget used on the eid field
             w(u'<td>%s</td>' % checkbox('eid', entity.eid, checked=qeid in values))
@@ -411,7 +411,7 @@
                 w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
                   (_('cancel this insert'), row[2]))
                 w(u'<a id="a%s" class="editionPending" href="%s">%s</a>'
-                  % (row[1], row[4], html_escape(row[5])))
+                  % (row[1], row[4], xml_escape(row[5])))
                 w(u'</td>')
                 w(u'</tr>')
         w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
@@ -419,7 +419,7 @@
         w(u'<span>%s</span>' % _('add relation'))
         w(u'<select id="relationSelector_%s" tabindex="%s" '
           'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
-          % (eid, req.next_tabindex(), html_escape(dumps(eid))))
+          % (eid, req.next_tabindex(), xml_escape(dumps(eid))))
         w(u'<option value="">%s</option>' % _('select a relation'))
         for i18nrtype, rschema, target in srels_by_cat:
             # more entities to link to
--- a/web/views/ibreadcrumbs.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/ibreadcrumbs.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
 from cubicweb.interfaces import IBreadCrumbs
@@ -21,7 +21,7 @@
 
 def bc_title(entity):
     textsize = entity.req.property_value('navigation.short-line-size')
-    return html_escape(cut(entity.dc_title(), textsize))
+    return xml_escape(cut(entity.dc_title(), textsize))
 
 
 class BreadCrumbEntityVComponent(EntityVComponent):
@@ -64,7 +64,7 @@
             url, title = part
             textsize = self.req.property_value('navigation.short-line-size')
             self.w(u'<a href="%s">%s</a>' % (
-                html_escape(url), html_escape(cut(title, textsize))))
+                xml_escape(url), xml_escape(cut(title, textsize))))
         else:
             textsize = self.req.property_value('navigation.short-line-size')
             self.w(cut(unicode(part), textsize))
@@ -81,6 +81,6 @@
 
     def cell_call(self, row, col):
         entity = self.entity(row, col)
-        desc = html_escape(cut(entity.dc_description(), 50))
+        desc = xml_escape(cut(entity.dc_description(), 50))
         self.w(u'<a href="%s" title="%s">%s</a>' % (
-            html_escape(entity.absolute_url()), desc, bc_title(entity)))
+            xml_escape(entity.absolute_url()), desc, bc_title(entity)))
--- a/web/views/idownloadable.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/idownloadable.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import BINARY_ENCODINGS, TransformError, html_escape
+from logilab.mtconverter import BINARY_ENCODINGS, TransformError, xml_escape
 
 from cubicweb.view import EntityView
 from cubicweb.selectors import (one_line_rset, score_entity,
@@ -31,12 +31,12 @@
     if title is None:
         title = req._('download')
     w(u'<div class="sideBoxTitle downloadBoxTitle"><span>%s</span></div>'
-      % html_escape(title))
+      % xml_escape(title))
     w(u'<div class="sideBox downloadBox"><div class="sideBoxBody">')
     w(u'<a href="%s"><img src="%s" alt="%s"/> %s</a>'
-      % (html_escape(entity.download_url()),
+      % (xml_escape(entity.download_url()),
          req.external_resource('DOWNLOAD_ICON'),
-         _('download icon'), html_escape(label or entity.dc_title())))
+         _('download icon'), xml_escape(label or entity.dc_title())))
     w(u'</div>')
     w(u'</div>\n</div>\n')
 
@@ -92,8 +92,8 @@
 
     def cell_call(self, row, col, title=None, **kwargs):
         entity = self.entity(row, col)
-        url = html_escape(entity.download_url())
-        self.w(u'<a href="%s">%s</a>' % (url, html_escape(title or entity.dc_title())))
+        url = xml_escape(entity.download_url())
+        self.w(u'<a href="%s">%s</a>' % (url, xml_escape(title or entity.dc_title())))
 
 
 class IDownloadablePrimaryView(primary.PrimaryView):
@@ -124,9 +124,9 @@
     def cell_call(self, row, col, title=None, **kwargs):
         """the secondary view is a link to download the file"""
         entity = self.entity(row, col)
-        url = html_escape(entity.absolute_url())
-        name = html_escape(title or entity.download_file_name())
-        durl = html_escape(entity.download_url())
+        url = xml_escape(entity.absolute_url())
+        name = xml_escape(title or entity.download_file_name())
+        durl = xml_escape(entity.download_url())
         self.w(u'<a href="%s">%s</a> [<a href="%s">%s</a>]' %
                (url, name, durl, self.req._('download')))
 
@@ -147,6 +147,6 @@
     def cell_call(self, row, col):
         entity = self.entity(row, col)
         #if entity.data_format.startswith('image/'):
-        self.w(u'<img src="%s" alt="%s"/>' % (html_escape(entity.download_url()),
-                                              html_escape(entity.download_file_name())))
+        self.w(u'<img src="%s" alt="%s"/>' % (xml_escape(entity.download_url()),
+                                              xml_escape(entity.download_file_name())))
 
--- a/web/views/iprogress.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/iprogress.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import implements
 from cubicweb.interfaces import IProgress, IMileStone
@@ -99,7 +99,7 @@
                 colname = meth(ecls)
             else:
                 colname = _(column)
-            self.w(u'<th>%s</th>' % html_escape(colname))
+            self.w(u'<th>%s</th>' % xml_escape(colname))
         self.w(u'</tr></thead>\n')
 
 
@@ -117,7 +117,7 @@
 
     def build_state_cell(self, entity):
         """``state`` column cell renderer"""
-        return html_escape(self.req._(entity.state))
+        return xml_escape(self.req._(entity.state))
 
     def build_eta_date_cell(self, entity):
         """``eta_date`` column cell renderer"""
--- a/web/views/isioc.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/isioc.py	Wed Jul 08 10:45:31 2009 +0200
@@ -7,7 +7,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.view import EntityView
 from cubicweb.selectors import implements
@@ -45,11 +45,11 @@
 
     def cell_call(self, row, col):
         entity = self.complete_entity(row, col)
-        sioct = html_escape(entity.isioc_type())
+        sioct = xml_escape(entity.isioc_type())
         self.w(u'<sioc:%s rdf:about="%s">\n'
-               % (sioct, html_escape(entity.absolute_url())))
+               % (sioct, xml_escape(entity.absolute_url())))
         self.w(u'<dcterms:title>%s</dcterms:title>'
-               % html_escape(entity.dc_title()))
+               % xml_escape(entity.dc_title()))
         self.w(u'<dcterms:created>%s</dcterms:created>'
                % entity.creation_date)
         self.w(u'<dcterms:modified>%s</dcterms:modified>'
@@ -66,25 +66,25 @@
 
     def cell_call(self, row, col):
         entity = self.complete_entity(row, col)
-        sioct = html_escape(entity.isioc_type())
+        sioct = xml_escape(entity.isioc_type())
         self.w(u'<sioc:%s rdf:about="%s">\n'
-               %  (sioct, html_escape(entity.absolute_url())))
+               %  (sioct, xml_escape(entity.absolute_url())))
         self.w(u'<dcterms:title>%s</dcterms:title>'
-               % html_escape(entity.dc_title()))
+               % xml_escape(entity.dc_title()))
         self.w(u'<dcterms:created>%s</dcterms:created>'
                % entity.creation_date)
         self.w(u'<dcterms:modified>%s</dcterms:modified>'
                % entity.modification_date)
         if entity.content:
             self.w(u'<sioc:content>%s</sioc:content>'''
-                   % html_escape(entity.isioc_content()))
+                   % xml_escape(entity.isioc_content()))
         if entity.related('entry_of'):
             self.w(u'<sioc:has_container rdf:resource="%s"/>\n'
-                   % html_escape(entity.isioc_container().absolute_url()))
+                   % xml_escape(entity.isioc_container().absolute_url()))
         if entity.creator:
             self.w(u'<sioc:has_creator>\n')
             self.w(u'<sioc:User rdf:about="%s">\n'
-                   % html_escape(entity.creator.absolute_url()))
+                   % xml_escape(entity.creator.absolute_url()))
             self.w(entity.creator.view('foaf'))
             self.w(u'</sioc:User>\n')
             self.w(u'</sioc:has_creator>\n')
--- a/web/views/management.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/management.py	Wed Jul 08 10:45:31 2009 +0200
@@ -9,7 +9,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import yes, none_rset, match_user_groups, authenticated_user
 from cubicweb.view import AnyRsetView, StartupView, EntityView
@@ -84,8 +84,8 @@
         _ = self.req._
         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
           % (entity.dc_type().capitalize(),
-             html_escape(entity.absolute_url()),
-             html_escape(entity.dc_title())))
+             xml_escape(entity.absolute_url()),
+             xml_escape(entity.dc_title())))
         # first show permissions defined by the schema
         self.w('<h2>%s</h2>' % _('schema\'s permissions definitions'))
         self.schema_definition(entity.e_schema)
@@ -141,7 +141,7 @@
                 # and this will replace %s by %25s
                 delurl += '&__delete=%s:require_permission:%%s' % entity.eid
                 dellinktempl = u'[<a href="%s" title="%s">-</a>]&nbsp;' % (
-                    html_escape(delurl), _('delete this permission'))
+                    xml_escape(delurl), _('delete this permission'))
             else:
                 dellinktempl = None
             w(u'<table class="schemaInfo">')
@@ -218,14 +218,14 @@
         if excinfo is not None and self.config['print-traceback']:
             if exclass is None:
                 w(u'<div class="tb">%s</div>'
-                       % html_escape(ex).replace("\n","<br />"))
+                       % xml_escape(ex).replace("\n","<br />"))
             else:
                 w(u'<div class="tb">%s: %s</div>'
-                       % (exclass, html_escape(ex).replace("\n","<br />")))
+                       % (exclass, xml_escape(ex).replace("\n","<br />")))
             w(u'<hr />')
             w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
         else:
-            w(u'<div class="tb">%s</div>' % (html_escape(ex).replace("\n","<br />")))
+            w(u'<div class="tb">%s</div>' % (xml_escape(ex).replace("\n","<br />")))
         # if excinfo is not None, it's probably not a bug
         if excinfo is None:
             return
@@ -272,7 +272,7 @@
             return unicode(repr(ex), encoding, 'replace')
 
 def text_error_description(ex, excinfo, req, eversion, cubes):
-    binfo = rest_traceback(excinfo, html_escape(ex))
+    binfo = rest_traceback(excinfo, xml_escape(ex))
     binfo += u'\n\n:URL: %s\n' % req.url()
     if not '__bugreporting' in req.form:
         binfo += u'\n:form params:\n'
@@ -322,7 +322,7 @@
         self.w(u'<table border="1">')
         for attr in env.keys():
             self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'
-                   % (attr, html_escape(env[attr])))
+                   % (attr, xml_escape(env[attr])))
         self.w(u'</table>')
         self.w(u'<h3>%s</h3>' % _('Request'))
         self.w(u'<table border="1">')
@@ -331,7 +331,7 @@
                      'search_state', 'the_request', 'unparsed_uri', 'uri'):
             val = getattr(req, attr)
             self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'
-                   % (attr, html_escape(val)))
+                   % (attr, xml_escape(val)))
         self.w(u'</table>')
         server = req.server
         self.w(u'<h3>%s</h3>' % _('Server'))
@@ -341,6 +341,6 @@
             if attr.startswith('_') or callable(val):
                 continue
             self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'
-                   % (attr, html_escape(val)))
+                   % (attr, xml_escape(val)))
         self.w(u'</table>')
 
--- a/web/views/navigation.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/navigation.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 
 from rql.nodes import VariableRef, Constant
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 from logilab.common.deprecation import obsolete
 
 from cubicweb.interfaces import IPrevNext
@@ -135,7 +135,7 @@
     def format_link_content(self, startstr, stopstr):
         text = u'%s - %s' % (startstr.lower()[:self.nb_chars],
                              stopstr.lower()[:self.nb_chars])
-        return html_escape(text)
+        return xml_escape(text)
 
     def write_links(self, params, blocklist):
         self.w(u'<div class="pagination">')
@@ -158,7 +158,7 @@
         nav.clean_params(params)
         # make a link to see them all
         if show_all_option:
-            url = html_escape(self.build_url(__force_display=1, **params))
+            url = xml_escape(self.build_url(__force_display=1, **params))
             w(u'<p><a href="%s">%s</a></p>\n'
               % (url, req._('show %s results') % len(rset)))
         rset.limit(offset=start, limit=stop-start, inplace=True)
@@ -197,24 +197,24 @@
                 self.w(self.previous_link(previous, textsize))
                 self.w(u'</div>')
                 self.req.html_headers.add_raw('<link rel="prev" href="%s" />'
-                                              % html_escape(previous.absolute_url()))
+                                              % xml_escape(previous.absolute_url()))
             if next:
                 self.w(u'<div class="nextEntity right">')
                 self.w(self.next_link(next, textsize))
                 self.w(u'</div>')
                 self.req.html_headers.add_raw('<link rel="next" href="%s" />'
-                                              % html_escape(next.absolute_url()))
+                                              % xml_escape(next.absolute_url()))
             self.w(u'</div>')
             self.w(u'<div class="clear"></div>')
 
     def previous_link(self, previous, textsize):
         return u'<a href="%s" title="%s">&lt;&lt; %s</a>' % (
-            html_escape(previous.absolute_url()),
+            xml_escape(previous.absolute_url()),
             self.req._('i18nprevnext_previous'),
-            html_escape(cut(previous.dc_title(), textsize)))
+            xml_escape(cut(previous.dc_title(), textsize)))
 
     def next_link(self, next, textsize):
         return u'<a href="%s" title="%s">%s &gt;&gt;</a>' % (
-            html_escape(next.absolute_url()),
+            xml_escape(next.absolute_url()),
             self.req._('i18nprevnext_next'),
-            html_escape(cut(next.dc_title(), textsize)))
+            xml_escape(cut(next.dc_title(), textsize)))
--- a/web/views/old_calendar.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/old_calendar.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 
 from datetime import date, time, timedelta
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.interfaces import ICalendarViews
 from cubicweb.utils import ONEDAY, ONEWEEK, date_range, first_day, last_day, previous_month, next_month, days_in_month
@@ -46,13 +46,13 @@
         next2 = next_month(date, bigshift)
         rql = self.rset.printable_rql()
         return self.NAV_HEADER % (
-            html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year,
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year,
                                        month=prev2.month)),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year,
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year,
                                        month=prev1.month)),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year,
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=next1.year,
                                        month=next1.month)),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year,
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=next2.year,
                                        month=next2.month)))
 
 
@@ -91,7 +91,7 @@
             rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.isocalendar()[1], ''.join(current_row)))
         url = self.build_url(rql=rql, vid='calendarmonth',
                              year=first_day.year, month=first_day.month)
-        monthlink = u'<a href="%s">%s</a>' % (html_escape(url), umonth)
+        monthlink = u'<a href="%s">%s</a>' % (xml_escape(url), umonth)
         return CALENDAR(self.req) % (monthlink, '\n'.join(rows))
 
     def _mk_schedule(self, begin, end, itemvid='calendaritem'):
@@ -203,7 +203,7 @@
             umonth = u'%s&nbsp;%s' % (self.format_date(cur_month, '%B'), cur_month.year)
             url = self.build_url(rql=rql, vid=self.id,
                                  year=cur_month.year, month=cur_month.month)
-            self.w(u'<th colspan="2"><a href="%s">%s</a></th>' % (html_escape(url),
+            self.w(u'<th colspan="2"><a href="%s">%s</a></th>' % (xml_escape(url),
                                                                   umonth))
         self.w(u'</tr>')
         _ = self.req._
@@ -272,7 +272,7 @@
             umonth = self.format_date(monday, '%B %Y')
             url = self.build_url(rql=rql, vid='calendarmonth',
                                  year=monday.year, month=monday.month)
-            monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+            monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth)
             self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \
                   % (_('week'), monday.isocalendar()[1], monthlink))
             for day in date_range(monday, sunday):
@@ -295,10 +295,10 @@
         next2 = date + ONEWEEK * bigshift
         rql = self.rset.printable_rql()
         return self.NAV_HEADER % (
-            html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year, week=prev2.isocalendar()[1])),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year, week=prev1.isocalendar()[1])),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year, week=next1.isocalendar()[1])),
-            html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year, week=next2.isocalendar()[1])))
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year, week=prev2.isocalendar()[1])),
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year, week=prev1.isocalendar()[1])),
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=next1.year, week=next1.isocalendar()[1])),
+            xml_escape(self.build_url(rql=rql, vid=self.id, year=next2.year, week=next2.isocalendar()[1])))
 
 
 
@@ -326,7 +326,7 @@
             if day.weekday() == 6:
                 url = self.build_url(rql=rql, vid='ampmcalendarweek',
                                      year=day.year, week=day.isocalendar()[1])
-                weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+                weeklink = '<a href="%s">%s</a>' % (xml_escape(url),
                                                     day.isocalendar()[1])
                 current_row.append(WEEKNUM_CELL % weeklink)
                 rows.append(current_row)
@@ -334,7 +334,7 @@
         current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (6-day.weekday()))
         url = self.build_url(rql=rql, vid='ampmcalendarweek',
                              year=day.year, week=day.isocalendar()[1])
-        weeklink = '<a href="%s">%s</a>' % (html_escape(url), day.isocalendar()[1])
+        weeklink = '<a href="%s">%s</a>' % (xml_escape(url), day.isocalendar()[1])
         current_row.append(WEEKNUM_CELL % weeklink)
         rows.append(current_row)
         # build two rows for each week: am & pm
@@ -350,7 +350,7 @@
         # tigh everything together
         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
                              year=first_day.year, month=first_day.month)
-        monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+        monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth)
         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
 
 
@@ -367,7 +367,7 @@
             umonth = u'%s&nbsp;%s' % (self.format_date(cur_month, '%B'), cur_month.year)
             url = self.build_url(rql=rql, vid=self.id,
                                  year=cur_month.year, month=cur_month.month)
-            self.w(u'<th colspan="3"><a href="%s">%s</a></th>' % (html_escape(url),
+            self.w(u'<th colspan="3"><a href="%s">%s</a></th>' % (xml_escape(url),
                                                                   umonth))
         self.w(u'</tr>')
         _ = self.req._
@@ -417,7 +417,7 @@
             if day.weekday() == 6:
                 url = self.build_url(rql=rql, vid='ampmcalendarweek',
                                      year=day.year, week=day.isocalendar()[1])
-                weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+                weeklink = '<a href="%s">%s</a>' % (xml_escape(url),
                                                     day.isocalendar()[1])
                 current_row.append(WEEKNUM_CELL % weeklink)
                 rows.append(current_row)
@@ -425,7 +425,7 @@
         current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (6-day.weekday()))
         url = self.build_url(rql=rql, vid='ampmcalendarweek',
                              year=day.year, week=day.isocalendar()[1])
-        weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+        weeklink = '<a href="%s">%s</a>' % (xml_escape(url),
                                             day.isocalendar()[1])
         current_row.append(WEEKNUM_CELL % weeklink)
         rows.append(current_row)
@@ -442,7 +442,7 @@
         # tigh everything together
         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
                              year=first_day.year, month=first_day.month)
-        monthlink = '<a href="%s">%s</a>' % (html_escape(url),
+        monthlink = '<a href="%s">%s</a>' % (xml_escape(url),
                                              umonth)
         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
 
@@ -461,7 +461,7 @@
             umonth = self.format_date(monday, '%B %Y')
             url = self.build_url(rql=rql, vid='ampmcalendarmonth',
                                  year=monday.year, month=monday.month)
-            monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+            monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth)
             w(u'<tr>%s</tr>' % (
                 WEEK_TITLE % (_('week'), monday.isocalendar()[1], monthlink)))
             w(u'<tr><th>%s</th><th>&nbsp;</th></tr>'% _(u'Date'))
--- a/web/views/plots.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/plots.py	Wed Jul 08 10:45:31 2009 +0200
@@ -13,7 +13,7 @@
 from simplejson import dumps
 
 from logilab.common import flatten
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.utils import make_uid, UStringIO, datetime2ticks
 from cubicweb.vregistry import objectify_selector
@@ -167,7 +167,7 @@
                 piechart.size(width, height)
             if self.title:
                 piechart.title(self.title)
-            self.w(u'<img src="%s" />' % html_escape(piechart.url))
+            self.w(u'<img src="%s" />' % xml_escape(piechart.url))
 
     class PieChartView(baseviews.AnyRsetView):
         id = 'piechart'
--- a/web/views/primary.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/primary.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 
 from warnings import warn
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import Unauthorized
 from cubicweb.view import EntityView
@@ -100,7 +100,7 @@
 
     def render_entity_title(self, entity):
         """default implementation return dc_title"""
-        title = html_escape(entity.dc_title())
+        title = xml_escape(entity.dc_title())
         if title:
             self.w(u'<h1><span class="etype">%s</span> %s</h1>'
                    % (entity.dc_type().capitalize(), title))
--- a/web/views/schema.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/schema.py	Wed Jul 08 10:45:31 2009 +0200
@@ -9,7 +9,7 @@
 
 from itertools import cycle
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 from yams import schema2dot as s2d
 
 from cubicweb.selectors import implements, yes
@@ -40,7 +40,7 @@
     def render_entity_title(self, entity):
         self.w(u'<h1><span class="etype">%s</span> %s</h1>'
                % (entity.dc_type().capitalize(),
-                  html_escape(entity.dc_long_title())))
+                  xml_escape(entity.dc_long_title())))
 
 
 # CWEType ######################################################################
@@ -119,8 +119,8 @@
         entity = self.entity(row, col)
         url = entity.absolute_url(vid='schemagraph')
         self.w(u'<img src="%s" alt="%s"/>' % (
-            html_escape(url),
-            html_escape(self.req._('graphical schema for %s') % entity.name)))
+            xml_escape(url),
+            xml_escape(self.req._('graphical schema for %s') % entity.name)))
 
 class CWETypeSPermView(EntityView):
     id = 'cwetype-schema-permissions'
@@ -157,8 +157,8 @@
         entity = self.entity(row, col)
         if entity.reverse_state_of:
             self.w(u'<img src="%s" alt="%s"/>' % (
-                    html_escape(entity.absolute_url(vid='ewfgraph')),
-                    html_escape(self.req._('graphical workflow for %s') % entity.name)))
+                    xml_escape(entity.absolute_url(vid='ewfgraph')),
+                    xml_escape(self.req._('graphical workflow for %s') % entity.name)))
         else:
             self.w(u'<p>%s</p>' % _('There is no workflow defined for this entity.'))
 
--- a/web/views/startup.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/startup.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 _ = unicode
 
 from logilab.common.textutils import unormalize
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.view import StartupView
 from cubicweb.selectors import match_user_groups, implements
@@ -77,7 +77,7 @@
             else:
                 href = req.build_url('view', vid='creation', etype='Card', wikiid='index')
                 label = self.req._('create an index page')
-            self.w(u'<br/><a href="%s">%s</a>\n' % (html_escape(href), label))
+            self.w(u'<br/><a href="%s">%s</a>\n' % (xml_escape(href), label))
 
     def folders(self):
         self.w(u'<h4>%s</h4>\n' % self.req._('Browse by category'))
@@ -92,7 +92,7 @@
             if v.category != 'startupview' or v.id in ('index', 'tree', 'manage'):
                 continue
             self.w('<p><a href="%s">%s</a></p>' % (
-                html_escape(v.url()), html_escape(self.req._(v.title).capitalize())))
+                xml_escape(v.url()), xml_escape(self.req._(v.title).capitalize())))
 
     def entities(self):
         schema = self.schema
@@ -146,7 +146,7 @@
             else:
                 url = self.build_url('view', rql='%s X' % etype)
             etypelink = u'&nbsp;<a href="%s">%s</a> (%d)' % (
-                html_escape(url), label, nb)
+                xml_escape(url), label, nb)
             yield (label, etypelink, self.add_entity_link(eschema, req))
 
     def add_entity_link(self, eschema, req):
@@ -154,7 +154,7 @@
         if not eschema.has_perm(req, 'add'):
             return u''
         return u'[<a href="%s" title="%s">+</a>]' % (
-            html_escape(self.create_url(eschema.type)),
+            xml_escape(self.create_url(eschema.type)),
             self.req.__('add a %s' % eschema))
 
 
@@ -186,9 +186,9 @@
         self.w(_(u'<div>This schema of the data model <em>excludes</em> the '
                  u'meta-data, but you can also display a <a href="%s">complete '
                  u'schema with meta-data</a>.</div>')
-               % html_escape(self.build_url('view', vid='schemagraph', withmeta=1)))
+               % xml_escape(self.build_url('view', vid='schemagraph', withmeta=1)))
         self.w(u'<img src="%s" alt="%s"/>\n' % (
-            html_escape(self.req.build_url('view', vid='schemagraph', withmeta=0)),
+            xml_escape(self.req.build_url('view', vid='schemagraph', withmeta=0)),
             self.req._("graphical representation of the application'schema")))
 
 
@@ -234,14 +234,14 @@
         self.w(u'<h4>%s</h4>' %   _('Entities').capitalize())
         ents = []
         for eschema in sorted(entities):
-            url = html_escape(self.build_url('schema', **formparams))
+            url = xml_escape(self.build_url('schema', **formparams))
             ents.append(u'<a class="grey" href="%s#%s">%s</a> (%s)' % (
                 url,  eschema.type, eschema.type, _(eschema.type)))
         self.w(u', '.join(ents))
         self.w(u'<h4>%s</h4>' % (_('relations').capitalize()))
         rels = []
         for rschema in sorted(relations):
-            url = html_escape(self.build_url('schema', **formparams))
+            url = xml_escape(self.build_url('schema', **formparams))
             rels.append(u'<a class="grey" href="%s#%s">%s</a> (%s), ' %  (
                 url , rschema.type, rschema.type, _(rschema.type)))
         self.w(u', '.join(ents))
@@ -259,7 +259,7 @@
         for eschema in sorted(entities):
             self.w(u'<a id="%s" href="%s"/>' %  (eschema.type, eschema.type))
             self.w(u'<h3 class="schema">%s (%s) ' % (eschema.type, _(eschema.type)))
-            url = html_escape(self.build_url('schema', **formparams) + '#index')
+            url = xml_escape(self.build_url('schema', **formparams) + '#index')
             self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
             self.w(u'</h3>')
             self.w(u'<div style="margin: 0px 1.5em">')
@@ -289,7 +289,7 @@
         for rschema in sorted(relations):
             self.w(u'<a id="%s" href="%s"/>' %  (rschema.type, rschema.type))
             self.w(u'<h3 class="schema">%s (%s) ' % (rschema.type, _(rschema.type)))
-            url = html_escape(self.build_url('schema', **formparams) + '#index')
+            url = xml_escape(self.build_url('schema', **formparams) + '#index')
             self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
             self.w(u'</h3>')
             self.w(u'<div style="margin: 0px 1.5em">')
--- a/web/views/tableview.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/tableview.py	Wed Jul 08 10:45:31 2009 +0200
@@ -10,7 +10,7 @@
 
 from simplejson import dumps
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import nonempty_rset, match_form_params
 from cubicweb.utils import make_uid
@@ -55,7 +55,7 @@
         # drop False / None values from vidargs
         vidargs = dict((k, v) for k, v in vidargs.iteritems() if v)
         self.w(u'<form method="post" cubicweb:facetargs="%s" action="">' %
-               html_escape(dumps([divid, 'table', False, vidargs])))
+               xml_escape(dumps([divid, 'table', False, vidargs])))
         self.w(u'<fieldset id="%sForm" class="%s">' % (divid, hidden and 'hidden' or ''))
         self.w(u'<input type="hidden" name="divid" value="%s" />' % divid)
         filter_hiddens(self.w, facets=','.join(wdg.facet.id for wdg in fwidgets), baserql=baserql)
@@ -178,7 +178,7 @@
         box = MenuWidget('', 'tableActionsBox', _class='', islist=False)
         label = '<img src="%s" alt="%s"/>' % (
             self.req.datadir_url + 'liveclipboard-icon.png',
-            html_escape(self.req._('action(s) on this selection')))
+            xml_escape(self.req._('action(s) on this selection')))
         menu = PopupBoxMenu(label, isitem=False, link_class='actionsBox',
                             ident='%sActions' % divid)
         box.append(menu)
--- a/web/views/tabs.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/tabs.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 
 __docformat__ = "restructuredtext en"
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb import NoSelectableObject, role
 from cubicweb.selectors import partial_has_related_entities
@@ -47,7 +47,7 @@
         elif rset:
             urlparams['rql'] = rset.printable_rql()
         w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % (
-            vid, html_escape(self.build_url('json', **urlparams))))
+            vid, xml_escape(self.build_url('json', **urlparams))))
         if show_spinbox:
             w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>'
               % (vid, self.req._('loading')))
--- a/web/views/timeline.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/timeline.py	Wed Jul 08 10:45:31 2009 +0200
@@ -11,7 +11,7 @@
 
 import simplejson
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.interfaces import ICalendarable
 from cubicweb.selectors import implements
@@ -68,7 +68,7 @@
         if start is None and stop is None:
             return None
         event_data = {'start': start.strftime(self.date_fmt),
-                      'title': html_escape(entity.dc_title()),
+                      'title': xml_escape(entity.dc_title()),
                       'description': entity.dc_description(format='text/html'),
                       'link': entity.absolute_url(),
                       }
@@ -95,7 +95,7 @@
             additional = u''
         self.w(u'<div class="widget" cubicweb:wdgtype="%s" '
                u'cubicweb:loadtype="auto" cubicweb:loadurl="%s" %s >' %
-               (self.widget_class, html_escape(loadurl),
+               (self.widget_class, xml_escape(loadurl),
                 additional))
         self.w(u'</div>')
 
--- a/web/views/timetable.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/timetable.py	Wed Jul 08 10:45:31 2009 +0200
@@ -6,7 +6,7 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.interfaces import ITimetableViews
 from cubicweb.selectors import implements
@@ -190,7 +190,7 @@
                     if value:
                         task_descr, first_row = value
                         if first_row:
-                            url = html_escape(task_descr.task.absolute_url(vid="edition"))
+                            url = xml_escape(task_descr.task.absolute_url(vid="edition"))
                             self.w(u'<td rowspan="%d" class="%s %s" onclick="document.location=\'%s\'">&nbsp;<div>' % (
                                 task_descr.lines, task_descr.color, filled_klasses[kj], url))
                             task_descr.task.view('tooltip', w=self.w)
--- a/web/views/treeview.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/treeview.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 
 from logilab.common.decorators import monkeypatch
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.utils import make_uid
 from cubicweb.interfaces import ITree
@@ -113,7 +113,7 @@
             w(u'<li class="%s">' % u' '.join(liclasses))
         else:
             rql = entity.children_rql() % {'x': entity.eid}
-            url = html_escape(self.build_url('json', rql=rql, vid=parentvid,
+            url = xml_escape(self.build_url('json', rql=rql, vid=parentvid,
                                              pageid=self.req.pageid,
                                              treeid=treeid,
                                              fname='view',
--- a/web/views/workflow.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/workflow.py	Wed Jul 08 10:45:31 2009 +0200
@@ -11,7 +11,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 from logilab.common.graph import escape, GraphGenerator, DotBackend
 
 from cubicweb import Unauthorized, view
@@ -119,7 +119,7 @@
     __select__ = implements('State')
 
     def cell_call(self, row, col):
-        self.w(html_escape(self.view('textincontext', self.rset,
+        self.w(xml_escape(self.view('textincontext', self.rset,
                                      row=row, col=col)))
 
 
@@ -146,8 +146,8 @@
         self.w(u'<h1>%s</h1>' % (self.req._('workflow for %s')
                                  % display_name(self.req, entity.name)))
         self.w(u'<img src="%s" alt="%s"/>' % (
-            html_escape(entity.absolute_url(vid='ewfgraph')),
-            html_escape(self.req._('graphical workflow for %s') % entity.name)))
+            xml_escape(entity.absolute_url(vid='ewfgraph')),
+            xml_escape(self.req._('graphical workflow for %s') % entity.name)))
 
 
 class WorkflowDotPropsHandler(object):
--- a/web/views/xbel.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/views/xbel.py	Wed Jul 08 10:45:31 2009 +0200
@@ -8,7 +8,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import implements
 from cubicweb.view import EntityView
@@ -42,8 +42,8 @@
 
     def cell_call(self, row, col):
         entity = self.complete_entity(row, col)
-        self.w(u'<bookmark href="%s">' % html_escape(self.url(entity)))
-        self.w(u'  <title>%s</title>' % html_escape(entity.dc_title()))
+        self.w(u'<bookmark href="%s">' % xml_escape(self.url(entity)))
+        self.w(u'  <title>%s</title>' % xml_escape(entity.dc_title()))
         self.w(u'</bookmark>')
 
     def url(self, entity):
--- a/web/widgets.py	Wed Jul 08 10:44:37 2009 +0200
+++ b/web/widgets.py	Wed Jul 08 10:45:31 2009 +0200
@@ -12,7 +12,7 @@
 
 from datetime import datetime
 
-from logilab.mtconverter import html_escape
+from logilab.mtconverter import xml_escape
 
 from yams.constraints import SizeConstraint, StaticVocabularyConstraint
 
@@ -247,9 +247,9 @@
         value = self.current_value(entity)
         dvalue = self.current_display_value(entity)
         if isinstance(value, basestring):
-            value = html_escape(value)
+            value = xml_escape(value)
         if isinstance(dvalue, basestring):
-            dvalue = html_escape(dvalue)
+            dvalue = xml_escape(dvalue)
         return u'%s<input type="%s" name="%s" value="%s" %s/>' % (
             self.hidden_input(entity, value), self.input_type,
             self.rname, dvalue, self.format_attrs())
@@ -323,9 +323,9 @@
         value = self.current_value(entity)
         dvalue = self.current_display_value(entity)
         if isinstance(value, basestring):
-            value = html_escape(value)
+            value = xml_escape(value)
         if isinstance(dvalue, basestring):
-            dvalue = html_escape(dvalue)
+            dvalue = xml_escape(dvalue)
         iid = self.attrs.pop('id')
         if self.required(entity):
             cssclass = u' required'
@@ -337,7 +337,7 @@
                     'iid': iid,
                     'hidden': self.hidden_input(entity, value),
                     'wdgtype': self.wdgtype,
-                    'url': html_escape(dataurl),
+                    'url': xml_escape(dataurl),
                     'tabindex': self.attrs.pop('tabindex'),
                     'value': dvalue,
                     'attrs': self.format_attrs(),
@@ -398,7 +398,7 @@
         editor = self._edit_render_textarea(entity, with_format)
         value = self.current_value(entity)
         if isinstance(value, basestring):
-            value = html_escape(value)
+            value = xml_escape(value)
         return u'%s%s' % (self.hidden_input(entity, value), editor)
 
     def _edit_render_textarea(self, entity, with_format):
@@ -406,7 +406,7 @@
         self.attrs.setdefault('rows', 20)
         dvalue = self.current_display_value(entity)
         if isinstance(dvalue, basestring):
-            dvalue = html_escape(dvalue)
+            dvalue = xml_escape(dvalue)
         if entity.use_fckeditor(self.name):
             entity.req.fckeditor_config()
             if with_format:
@@ -472,9 +472,9 @@
             or entity.e_schema.has_metadata(self.name, 'encoding')):
             divid = '%s-%s-advanced' % (self.name, entity.eid)
             wdgs.append(u'<a href="%s" title="%s"><img src="%s" alt="%s"/></a>' %
-                        (html_escape(toggle_action(divid)),
+                        (xml_escape(toggle_action(divid)),
                          req._('show advanced fields'),
-                         html_escape(req.build_url('data/puce_down.png')),
+                         xml_escape(req.build_url('data/puce_down.png')),
                          req._('show advanced fields')))
             wdgs.append(u'<div id="%s" class="hidden">' % divid)
             for extraattr in ('_format', '_encoding'):
@@ -572,7 +572,7 @@
                 res.append(u'<optgroup label="%s"/>' % (label or ''))
             else:
                 value, flag = self.form_value(entity, value, dvalues)
-                res.append(u'<option value="%s" %s>%s</option>' % (value, flag, html_escape(label)))
+                res.append(u'<option value="%s" %s>%s</option>' % (value, flag, xml_escape(label)))
         res.append(u'</select>')
         return '\n'.join(res)
 
@@ -658,7 +658,7 @@
                 res.append(u'<optgroup label="%s"/>' % (label or ''))
             else:
                 value, flag = self.form_value(entity, value, dvalues)
-                res.append(u'<option value="%s" %s>%s</option>' % (value, flag, html_escape(label)))
+                res.append(u'<option value="%s" %s>%s</option>' % (value, flag, xml_escape(label)))
         res.append(u'</select>')
         res.append(u'<div id="newvalue">')
         res.append(u'<input type="text" id="newopt" />')
@@ -819,7 +819,7 @@
         url = getattr(entity, self.name)
         if not url:
             return u''
-        url = html_escape(url)
+        url = xml_escape(url)
         return u'<a href="%s">%s</a>' % (url, url)
 
 class EmbededURLWidget(StringWidget):
@@ -828,7 +828,7 @@
         url = getattr(entity, self.name)
         if not url:
             return u''
-        aurl = html_escape(entity.build_url('embed', url=url))
+        aurl = xml_escape(entity.build_url('embed', url=url))
         return u'<a href="%s">%s</a>' % (aurl, url)