Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/binary.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/binary.py	(revision 1413)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/binary.py	(revision 1414)
@@ -24,4 +24,6 @@
         #self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_fields')
         self.excludekey = options.get('exclude-key', '_excluded_fields').strip()
+        
+        self.doc = minidom.Document()
 
     def __iter__(self):
@@ -73,5 +75,11 @@
         """
         field = obj.getField(field)
-        base_unit = field.getBaseUnit(obj)
+        # temporarily:
+        # dirty call, I know, just lazy to get method arguments
+        # TextField overrided getBaseUnit method but didn't follow API
+        try:
+            base_unit = field.getBaseUnit(obj, full=True)
+        except TypeError, e:
+            base_unit = field.getBaseUnit(obj)
         fname = base_unit.getFilename() 
         ct = base_unit.getContentType()
@@ -81,12 +89,41 @@
 
     def createManifest(self, binary_fields):
-        manifest = '<?xml version="1.0" ?>\n<manifest>\n'
-        for field, info in binary_fields.items():
-            manifest += '  <field name="%s">\n' % field
-            manifest += '    <filename>%s</filename>\n' % info['filename']
-            manifest += '    <mimetype>%s</mimetype>\n' % info['mimetype']
-            manifest += '  </field>\n'
-        manifest += "</manifest>\n"
-        return manifest
+        doc = self.doc
+
+        root = doc.createElement('manifest')
+        for fname, info in binary_fields.items():
+            # create field node
+            field = doc.createElement('field')
+
+            # set name attribute
+            attr = doc.createAttribute('name')
+            attr.value = fname
+            field.setAttributeNode(attr)
+
+            # create filename node
+            filename = doc.createElement('filename')
+            filename.appendChild(doc.createTextNode(info['filename']))
+            field.appendChild(filename)
+
+            # create mimetype node
+            mimetype = doc.createElement('mimetype')
+            mimetype.appendChild(doc.createTextNode(info['mimetype']))
+            field.appendChild(mimetype)
+
+            root.appendChild(field)
+
+        doc.appendChild(root)
+
+        try:
+            data = doc.toprettyxml(indent='  ', encoding='utf-8')
+        except UnicodeDecodeError, e:
+            # all comments are strings encoded in 'utf-8' and they will properly
+            # saved in xml file, but if we explicitly give 'utf-8' encoding
+            # UnicodeDecodeError will be raised when they have non-ascii chars
+            data = doc.toprettyxml(indent='  ')
+
+        doc.unlink()
+        return data
+
 
 class FileImporterSection(object):
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/manifest.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/manifest.py	(revision 1413)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/manifest.py	(revision 1414)
@@ -21,4 +21,6 @@
         self.fileskey = options.get('files-key', '_files').strip()
 
+        self.doc = minidom.Document()
+
     def __iter__(self):
         for item in self.previous:
@@ -41,9 +43,35 @@
         if not entries:
             return None
-        manifest = '<?xml version="1.0" ?>\n<manifest>\n'
+
+        doc = self.doc
+        root = doc.createElement('manifest')
+
         for obj_id, obj_type in entries:
-            manifest += '  <record type="%s">%s</record>\n' % (obj_type, obj_id)
-        manifest += "</manifest>\n"
-        return manifest
+            # create record
+            record = doc.createElement('record')
+
+            # set type attribute
+            attr = doc.createAttribute('type')
+            attr.value = obj_type
+            record.setAttributeNode(attr)
+
+            # add object id
+            text = doc.createTextNode(obj_id)
+            record.appendChild(text)
+
+            root.appendChild(record)
+
+        doc.appendChild(root)
+
+        try:
+            data = doc.toprettyxml(indent='  ', encoding='utf-8')
+        except UnicodeDecodeError, e:
+            # all comments are strings encoded in 'utf-8' and they will properly
+            # saved in xml file, but if we explicitly give 'utf-8' encoding
+            # UnicodeDecodeError will be raised when they have non-ascii chars
+            data = doc.toprettyxml(indent='  ')
+
+        doc.unlink()
+        return data
 
 class ManifestImporterSection(object):
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/marshall.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/marshall.py	(revision 1413)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/marshall.py	(revision 1414)
@@ -15,4 +15,8 @@
 from Products.Archetypes.event import ObjectInitializedEvent
 from Products.Archetypes.event import ObjectEditedEvent
+
+# override Marshall atxml namespaces
+from quintagroup.transmogrifier import namespaces
+
 
 class MarshallerSection(object):
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/__init__.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/__init__.py	(revision 1414)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/__init__.py	(revision 1414)
@@ -0,0 +1,27 @@
+# import Products.Marshall namespaces to ensure it's registered
+# before we override it
+from Products.Marshall import namespaces
+from Products.Marshall.handlers.atxml import ATXMLMarshaller, XmlNamespace
+
+from atns import Archetypes
+from dcns import DublinCore
+from cmfns import CMF
+
+
+def replaceNamespace(ns):
+    """Replace namespaces by prefix"""
+    if not isinstance(ns, XmlNamespace):
+        ns = ns()
+
+    nses = ATXMLMarshaller.namespaces
+    prefixes = [nses.index(n) for n in nses if n.prefix == ns.prefix]
+    if len(prefixes) == 0:
+        return False
+
+    idx = prefixes[0]
+    nses.pop(idx)
+    nses.insert(idx, ns)
+
+replaceNamespace(DublinCore)
+replaceNamespace(Archetypes)
+replaceNamespace(CMF)
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/atns.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/atns.py	(revision 1414)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/atns.py	(revision 1414)
@@ -0,0 +1,106 @@
+"""
+    Archetypes Marshall namespace but which can safely handle
+    Control Characters for you
+"""
+
+from Products.Archetypes.interfaces.base import IBaseUnit
+
+from Products.Marshall import config
+from Products.Marshall.handlers.atxml import XmlNamespace
+from Products.Marshall.handlers.atxml import SchemaAttribute
+from Products.Marshall.handlers.atxml import getRegisteredNamespaces
+from Products.Marshall.exceptions import MarshallingException
+from Products.Marshall import utils
+
+from Products.Marshall.namespaces import atns as base
+
+from quintagroup.transmogrifier.namespaces.util import has_ctrlchars
+
+
+class ATAttribute(base.ATAttribute):
+
+    def serialize(self, dom, parent_node, instance, options={}):
+        
+        values = self.get(instance)
+        if not values:
+            return
+
+        is_ref = self.isReference(instance)
+        
+        for value in values:
+            node = dom.createElementNS(self.namespace.xmlns, "field")
+            name_attr = dom.createAttribute("name")
+            name_attr.value = self.name
+            node.setAttributeNode(name_attr)
+            
+            # try to get 'utf-8' encoded string
+            if isinstance(value, unicode):
+                value = value.encode('utf-8')
+            elif IBaseUnit.isImplementedBy(value):
+                value = value.getRaw(encoding='utf-8')
+            else:
+                value = str(value)
+
+            if is_ref:
+                if config.HANDLE_REFS:
+                    ref_node = dom.createElementNS(self.namespace.xmlns,
+                                                    'reference')
+                    uid_node = dom.createElementNS(self.namespace.xmlns,
+                                                    'uid')
+                    value = response.createTextNode(value)
+                    uid_node.append(value)
+                    ref_node.append(uid_node)
+                    node.append(ref_node)
+            elif isinstance(value, str) and has_ctrlchars(value):
+                value = value.encode('base64')
+                attr = dom.createAttributeNS(self.namespace.xmlns,
+                                             'transfer_encoding')
+                attr.value = 'base64'
+                node.setAttributeNode(attr)
+                value_node = dom.createCDATASection(value)
+                node.appendChild(value_node)
+            else:
+                value_node = dom.createTextNode(value)
+                node.appendChild(value_node)
+        
+            node.normalize()
+            parent_node.appendChild(node)
+
+        return True
+
+    def processXmlValue(self, context, value ):
+        value = value.strip()
+        if not value:
+            return
+
+        # decode node value if needed
+        te = context.node.get('transfer_encoding', None)
+        if te is not None:
+            value = value.decode(te)
+
+        data = context.getDataFor(self.namespace.xmlns)
+        if data.has_key(self.name):
+            svalues = data[self.name]
+            if not isinstance(svalues, list):
+                data[self.name] = svalues = [svalues]
+            svalues.append(value)
+            return
+        else:
+            data[self.name] = value
+
+class Archetypes(base.Archetypes):
+
+    def getAttributeByName(self, schema_name, context=None):
+        if context is not None and schema_name not in self.at_fields:
+            if not context.instance.Schema().has_key(schema_name):
+                return
+                raise AssertionError, \
+                      "invalid attribute %s"%(schema_name)
+        
+        if schema_name in self.at_fields:
+            return self.at_fields[schema_name]
+
+        attribute = ATAttribute(schema_name)
+        attribute.setNamespace(self)
+        
+        return attribute
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/cmfns.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/cmfns.py	(revision 1414)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/cmfns.py	(revision 1414)
@@ -0,0 +1,37 @@
+"""
+    CMF Marshall namespace is overrided here in order to fix
+    LocalRolesAttribute class. It's not working in Marshall Product.
+"""
+
+from Products.Marshall import utils
+from Products.Marshall.namespaces import cmfns as base
+
+
+class LocalRolesAttribute(base.LocalRolesAttribute):
+
+    def getAttributeNames(self):
+        return (self.name, 'security')
+    
+    def processXml(self, context, node):
+        tag, namespace = utils.fixtag(node.tag,context.ns_map)
+        nsprefix = node.tag[:node.tag.find('}')+1]
+        local_roles = node.findall(nsprefix+self.name)
+        
+        if len(local_roles) == 0:
+            return
+
+        data = context.getDataFor(self.namespace.xmlns)
+        values = data.setdefault(self.name, [])
+        
+        for lrole in local_roles:
+            values.append((lrole.get('user_id'), lrole.get('role')))
+        
+        return True
+    
+class CMF(base.CMF):
+    
+    attributes = (
+        base.TypeAttribute('type'),
+        base.WorkflowAttribute('workflow_history '),
+        LocalRolesAttribute('local_role')
+        )
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/dcns.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/dcns.py	(revision 1414)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/dcns.py	(revision 1414)
@@ -0,0 +1,80 @@
+"""
+    DublinCore Marshall namespace but which can safely handle
+    Control Characters for you
+"""
+
+from Products.Archetypes.interfaces.base import IBaseUnit
+
+from Products.Marshall.namespaces import dcns as base
+from Products.Marshall.namespaces.dcns import normalizer
+
+from quintagroup.transmogrifier.namespaces.util import has_ctrlchars
+
+
+class DCAttribute(base.DCAttribute):
+
+    def serialize(self, dom, parent_node, instance):
+        values = self.get(instance)
+        if not values:
+            return False
+        
+        for value in values:
+            elname = "%s:%s"%(self.namespace.prefix, self.name)
+            node = dom.createElementNS(base.DublinCore.xmlns, elname)
+
+            # try to get 'utf-8' encoded string
+            if isinstance(value, unicode):
+                value = value.encode('utf-8')
+            elif IBaseUnit.isImplementedBy(value):
+                value = value.getRaw(encoding='utf-8')
+            else:
+                value = str(value)
+
+            if isinstance(value, str) and has_ctrlchars(value):
+                value = value.encode('base64')
+                attr = dom.createAttributeNS(base.DublinCore.xmlns,
+                                             'transfer_encoding')
+                attr.value = 'base64'
+                node.setAttributeNode(attr)
+                value_node = dom.createCDATASection(value)
+            else:
+                value_node = dom.createTextNode(value)
+
+            node.appendChild(value_node)
+            node.normalize()
+            parent_node.appendChild(node)
+        return True
+
+    def processXmlValue(self, context, value):
+        value = value and value.strip()
+        if not value:
+            return
+
+        # decode node value if needed
+        te = context.node.get('transfer_encoding', None)
+        if te is not None:
+            value = value.decode(te)
+
+        data = context.getDataFor(self.namespace.xmlns)
+        if self.many:
+            data.setdefault(self.name, []).append(value)
+        else:
+            data[self.name]=value
+
+class DublinCore(base.DublinCore):
+    
+    attributes = (
+        DCAttribute('title', 'Title', 'setTitle',
+                    process=(normalizer.space, normalizer.newline)),
+        
+        DCAttribute('description', 'Description', 'setDescription',
+                    process=(normalizer.space,)),
+
+        DCAttribute('subject', 'Subject', 'setSubject', many=True),                
+        DCAttribute('contributor', 'Contributors', 'setContributors',
+                    many=True),
+        # this attr diverges from cmfdefault.dublincore
+        DCAttribute('creator', 'Creators', 'setCreators', many=True),
+        DCAttribute('rights', 'Rights', 'setRights'),
+        DCAttribute('language', 'Language', 'setLanguage')
+        )
Index: /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/util.py
===================================================================
--- /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/util.py	(revision 1414)
+++ /quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/namespaces/util.py	(revision 1414)
@@ -0,0 +1,18 @@
+"""
+    Helpful functions for namespaces
+"""
+
+import re
+
+# control characters from 0-31 and 127 (delete) excluding:
+#   9 (\t, tab)
+#   10 (\n, new line character)
+#   13 (\r, carriage return)
+#   127 (\x1f, delete)
+# which are handled properly by python xml libraries such
+# as xml.dom.minidom and elementtree
+_ctrl_chars = re.compile(r'[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]')
+def has_ctrlchars(value):
+    if _ctrl_chars.search(value):
+        return True
+    return False
