diff --git a/data/homeostasis_25nov.xml b/data/homeostasis_25nov.xml
index 78569881afb5b193104182522b69a1a7b0b1c06c..3472cbf4e064807e3ba49b28a9c27e7257e53d3a 100644
--- a/data/homeostasis_25nov.xml
+++ b/data/homeostasis_25nov.xml
@@ -104,7 +104,7 @@
             <keyword action="" lang="esp"> seis </keyword>
             <keyword action="#end" lang="eng"> open network </keyword>
         </sequence>
-        <sequence ordre="variable" repetition="oui" action="constellation/all words become written in the space constellation when they are pronounced/ the repetition of the same a word amplifies the word/" lang="eng">
+        <sequence ordre="variable" repetition="oui" action="constellation" lang="eng">
             <keyword action="constellation" lang="eng"> clouds </keyword>
             <keyword action="constellation" lang="eng"> beautiful </keyword>
             <keyword action="constellation" lang="eng"> data </keyword>
@@ -153,7 +153,7 @@
             <keyword action="#end"> try with functional regulation </keyword>
             <keyword action="#end" lang="eng"> give me my data </keyword>
         </sequence>
-        <sequence ordre="variable" repetition="oui" action="constellation/all words become written in the space constellation when they are pronounced/ the repetition of the same a word amplifies the word/" lang="eng">
+        <sequence ordre="variable" repetition="oui" action="constellation" lang="eng">
             <keyword action="constellation" lang="eng"> possible  </keyword>
             <keyword action="amplification1" lang="eng"> function </keyword>
             <keyword action="constellation" lang="eng"> erase the  </keyword>
@@ -392,7 +392,7 @@
             <keyword action="#end"> and to want </keyword>
             <keyword action="#end" lang="eng"> give me my data </keyword>
         </sequence>
-        <sequence ordre="variable" repetition="oui" lang="esp" action="constellation/all words become written in the space constellation when they are pronounced/ the repetition of the same a word amplifies the word/interlined words in groups of 12 or divided by silence">
+        <sequence ordre="variable" repetition="oui" lang="esp" action="constellation">
             como decir
             lo que la nada entiende
             lo que el miedo esconde
@@ -411,7 +411,7 @@
             <keyword action="#end"> y querer </keyword>
             <keyword action="#end" lang="eng"> give me my data </keyword>
         </sequence>
-        <sequence ordre="variable" repetition="oui" lang="eng" action="constellation/all words become written in the space constellation when they are pronounced/ the repetition of the same a word amplifies the word/interlined words in groups of 12 or divided by silence">
+        <sequence ordre="variable" repetition="oui" lang="eng" action="constellation">
             try with upper motoneuron
             functions 
             functions
diff --git a/validate.py b/validate.py
index d74f938a48a56520f067625ef5d2ea1da2362345..94afbcb79de1828eec2a902908ecf74629f908aa 100644
--- a/validate.py
+++ b/validate.py
@@ -3,6 +3,7 @@ import re
 
 seen_section_ids = {}
 seen_actions = {}
+warnings = []
 
 class VerifyException(Exception):
     def __init__(self, message, node):
@@ -17,10 +18,10 @@ def is_int(text):
     return re.match(r'^\d+$', text)
 
 def has_blank(text):
-    return re.match(r'\s', text)
+    return re.search(r'\s', text)
 
 def verify_keyword(node):
-    global seen_actions
+    global seen_actions, warnings
     for key in node.attrib:
         if key not in ['action', 'lang']:
             raise VerifyException('attribute "%s" not allowed in <%s>' % (key, node.tag), node)
@@ -28,10 +29,10 @@ def verify_keyword(node):
         if key not in node.attrib:
             raise VerifyException('node <%s> must contain attribute "%s"' % (node.tag, key), node)
     if node.get('action').strip() == '':
-        print 'WARNING: empty action for %s' % ET.tostring(node).strip()
+        warnings.append('WARNING: empty action for %s' % ET.tostring(node).strip())
         #raise VerifyException('empty action', node)
     if has_blank(node.get('action')):
-        raise VerifyException('spaces not allowed in action "%s"', node)
+        raise VerifyException('spaces not allowed in action "%s"' % node.get('action'), node)
     seen_actions[node.get('action')] = True
     if node.get('lang') not in [None, 'eng', 'esp']:
         raise VerifyException('unsupported lang "%s"' % node.get('lang'), node)
@@ -44,6 +45,8 @@ def verify_sequence(node):
             raise VerifyException('attribute "%s" not allowed in <%s>' % (key, node.tag), node)
     if node.get('lang') not in [None, 'eng', 'esp']:
         raise VerifyException('unsupported lang "%s"' % node.get('lang'), node)
+    if has_blank(node.get('action')):
+        raise VerifyException('spaces not allowed in action "%s"' % node.get('action'), node)
     for child in node:
         if child.tag == 'keyword':
             verify_keyword(child)
@@ -58,6 +61,8 @@ def verify_section(node):
     for key in ['id']:
         if key not in node.attrib:
             raise VerifyException('node <%s> must contain attribute "%s"' % (node.tag, key), node)
+    if has_blank(node.get('action')):
+        raise VerifyException('spaces not allowed in action "%s"' % node.get('action'), node)
     if not is_int(node.get('id')):
         raise VerifyException('only integers allowed for section id "%s"' % node.get('id'))
     if node.get('id') in seen_section_ids:
@@ -104,15 +109,20 @@ def verify_root(node):
         raise VerifyException('no text allowed directly after <%s>' % (node.tag), node)
 
 def validate_xml(filename):
-    global seen_section_ids, seen_actions
+    global seen_section_ids, seen_actions, warnings
     seen_section_ids = {}
     seen_actions = {}
+    warnings = []
     try:
         root = ET.parse(filename).getroot()
         verify_root(root)
     except Exception as e:
-        return (False, str(e))
-    return (True, 'successfuly validated "%s"\nfound %d sections, %d types of action' % (filename, len(seen_section_ids), len(seen_actions)))
+        if len(warnings) > 0:
+            warnings.append('--------------')
+        return (False, '\n'.join(warnings) + '\n' + str(e))
+    if len(warnings) > 0:
+        warnings.append('--------------')
+    return (True, '\n'.join(warnings) + '\nsuccessfuly validated "%s"\nfound %d sections, %d types of action' % (filename, len(seen_section_ids), len(seen_actions)))
 
 if __name__ == '__main__':
     import sys
diff --git a/xmledit.py b/xmledit.py
index b35b99682700e7cfde238c15fc44ee977337ef15..3d6b73cd4947760b412c6a028ad1c9b7de257c51 100644
--- a/xmledit.py
+++ b/xmledit.py
@@ -17,12 +17,12 @@ class SourceView(Gtk.Window):
     def __init__(self, filename):
         super(SourceView, self).__init__()
 
-        self.filename = filename
+        self.filename = None
 
         self.connect("destroy", self.quit)
-        self.set_default_size(800,600)
+        self.set_default_size(1024, 768)
         self.set_border_width(10)
-        self.set_title('SourceView')
+        self.set_title('Homeostasis editor')
 
         tabs = Gtk.Notebook()
         self.tabs = tabs
@@ -44,9 +44,13 @@ class SourceView(Gtk.Window):
         #vbox.pack_start(self.command, False, True, 5)
 
         hbox = Gtk.HBox()
-        revert_button = Gtk.Button('Revert')
-        revert_button.connect('clicked', self.load)
-        hbox.pack_start(revert_button, False, False, 5)
+        new_button = Gtk.Button('New')
+        new_button.connect('clicked', self.new)
+        hbox.pack_start(new_button, False, False, 5)
+
+        load_button = Gtk.Button('Load')
+        load_button.connect('clicked', lambda *args: self.show_filechooser("load"))
+        hbox.pack_start(load_button, False, False, 5)
 
         validate_button = Gtk.Button('Validate')
         validate_button.connect('clicked', self.validate)
@@ -60,37 +64,95 @@ class SourceView(Gtk.Window):
         save_button.connect('clicked', self.save)
         hbox.pack_start(save_button, False, False, 5)
 
+        saveas_button = Gtk.Button('Save as')
+        saveas_button.connect('clicked', lambda *args: self.show_filechooser("save"))
+        hbox.pack_start(saveas_button, False, False, 5)
+
         vbox.pack_start(tabs, True, True, 5)
         vbox.pack_start(hbox, False, True, 5)
 
-        tabs.append_page(self.scrolled, Gtk.Label(filename))
+        tabs.append_page(self.scrolled, Gtk.Label('xml filename'))
         tabs.append_page(self.command, Gtk.Label('Compilation result'))
         tabs.set_show_border(False)
 
+        self.set_filename(filename)
+        self.load()
+
         self.add(vbox)
         self.show_all()
 
-        self.load()
+        self.command.add_text('READY')
+
+    def new(self, *args):
+        self.source_buffer.set_text("""<homeostasis version="25-11-2014">
+    <liste_section sequences="1" ordre="variable" repetition="oui" action="exclusive">
+        <section id="2" action="example1">
+            <sequence ordre="strict" repetition="non" action="" lang="esp">
+                <keyword action="example2" lang="eng"> hello </keyword>
+            </sequence>
+        </section>
+    </liste_section>
+</homeostasis>""")
+        self.set_filename('unsaved')
+
+    def set_filename(self, filename):
+        self.filename = filename
+        self.tabs.set_tab_label(self.scrolled, Gtk.Label(os.path.basename(filename)))
 
-    def load(self, *args):
-        self.source_buffer.set_text(open(self.filename).read())
+    def show_filechooser(self, dialog_type="load"):
+        if dialog_type == "load":
+            dialog = Gtk.FileChooserDialog("Please choose a file to load", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+        else:
+            dialog = Gtk.FileChooserDialog("Please set a file to save", self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
+        filter_text = Gtk.FileFilter()
+        filter_text.set_name("XML files")
+        filter_text.add_mime_type("text/xml")
+        dialog.add_filter(filter_text)
+        dialog.set_current_folder('%s/data' % (os.path.dirname(__file__) or '.'))
+
+        response = dialog.run()
+        if response == -5:
+            self.filename = dialog.get_filename()
+            print self.filename
+            self.set_filename(self.filename)
+            dialog.destroy()
+            if dialog_type == "load":
+                return self.load()
+            else:
+                return self.save()
+        dialog.destroy()
 
-    def save(self, *args):
-        self.command.clear()
+    def load(self, *args):
         try:
-            with open('data/edited.xml', 'w') as fp:
-                bounds = self.source_buffer.get_bounds()
-                fp.write(self.source_buffer.get_text(bounds[0], bounds[1], True))
+            with open(self.filename) as fp:
+                self.source_buffer.set_text(fp.read())
         except Exception as e:
             print e
-            self.command.add_text('FAILED to save as data/edited.xml')
+            self.command.add_text('FAILED to load "%s"' % self.filename)
+            return False
+        return True
+
+    def save(self, *args):
+        if self.filename == 'unsaved':
+            return self.show_filechooser("save")
+        else:
+            self.command.clear()
+            try:
+                with open(self.filename, 'w') as fp:
+                    bounds = self.source_buffer.get_bounds()
+                    fp.write(self.source_buffer.get_text(bounds[0], bounds[1], True))
+            except Exception as e:
+                print e
+                self.command.add_text('FAILED to save as "%s"' % self.filename)
+                return False
+        return True
 
     def validate(self, *args):
         self.command.clear()
         self.save()
         self.command.add_text('VALIDATE...')
         self.tabs.set_current_page(1)
-        result, message = validate.validate_xml('data/edited.xml')
+        result, message = validate.validate_xml(self.filename)
         self.command.add_text(message)
         if result:
             self.command.add_text('SUCCESS')
@@ -101,10 +163,10 @@ class SourceView(Gtk.Window):
     def compile(self, *args):
         self.command.clear()
         self.tabs.set_current_page(1)
-        self.save()
-        self.validate()
-        self.command.add_text('COMPILE...')
-        self.command.run('./tools/compile.ben.sh data/edited.xml tools/model')
+        if self.save():
+            if self.validate():
+                self.command.add_text('COMPILE...')
+                self.command.run('./tools/compile.ben.sh "%s" tools/model' % self.filename)
 
     def quit(self, window):
         Gtk.main_quit()