Index: src/sas/sascalc/dataloader/readers/cansas_constants.py
===================================================================
--- src/sas/sascalc/dataloader/readers/cansas_constants.py	(revision d398285d1a07fbcba8a3328a6db3de09fb8581df)
+++ src/sas/sascalc/dataloader/readers/cansas_constants.py	(revision 250fec92ea66b0770da33360a90f022e1d674072)
@@ -27,5 +27,4 @@
         return_me.current_level = self.CANSAS_FORMAT.get("SASentry")
         # Defaults for variable and datatype
-        return_me.ns_variable = "{0}.meta_data[\"{2}\"] = \"{1}\""
         return_me.ns_datatype = "content"
         return_me.ns_optional = True
@@ -38,13 +37,10 @@
                         return_me.current_level = \
                                 return_me.current_level.get("<any>", "")
-                    cl_variable = return_me.current_level.get("variable", "")
                     cl_datatype = return_me.current_level.get("storeas", "")
                     cl_units_optional = \
-                             return_me.current_level.get("units_required", "")
+                             return_me.current_level.get("units_optional", "")
                     # Where are how to store the variable for the given
                     # namespace CANSAS_CONSTANTS tree is hierarchical, so
                     # is no value, inherit
-                    return_me.ns_variable = cl_variable if cl_variable != "" \
-                        else return_me.ns_variable
                     return_me.ns_datatype = cl_datatype if cl_datatype != "" \
                         else return_me.ns_datatype
@@ -53,5 +49,4 @@
                                         else return_me.ns_optional
             except AttributeError:
-                return_me.ns_variable = "{0}.meta_data[\"{2}\"] = \"{1}\""
                 return_me.ns_datatype = "content"
                 return_me.ns_optional = True
@@ -75,23 +70,12 @@
     # The constants below hold information on where to store the CanSAS data
     # when loaded in using sasview
-    META_DATA = "{0}.meta_data[\"{2}\"] = \"{1}\""
-    ANY = {"variable" : "{0}.meta_data[\"{2}\"] = \'{1}\'",
-           "storeas" : "content",
-          }
-    TITLE = {"variable" : "{0}.title = \"{1}\""}
-    SASNOTE = {"variable" : "{0}.notes.append(\'{1}\')"}
-    SASPROCESS_TERM = {"variable" : None,
-                       "attributes" : {"unit" : {"variable" : None},
-                                       "name" : {"variable" : None}
-                                      }
-                      }
-    SASPROCESS_SASPROCESSNOTE = {"variable" : None,
-                                 "children" : {"<any>" : ANY}
-                                }
-    SASPROCESS = {"variable" : None,
-                  "children" : {"name" : {"variable" : "{0}.name = \'{1}\'"},
-                                "date" : {"variable" : "{0}.date = \'{1}\'"},
-                                "description" :
-                                {"variable" : "{0}.description = \'{1}\'"},
+    ANY = {"storeas" : "content"}
+    TITLE = {}
+    SASNOTE = {}
+    SASPROCESS_TERM = {"attributes" : {"unit" : {}, "name" : {}}}
+    SASPROCESS_SASPROCESSNOTE = {"children" : {"<any>" : ANY}}
+    SASPROCESS = {"children" : {"name" : {},
+                                "date" : {},
+                                "description" : {},
                                 "term" : SASPROCESS_TERM,
                                 "SASprocessnote" : SASPROCESS_SASPROCESSNOTE,
@@ -99,74 +83,40 @@
                                },
                  }
-    RUN = {"variable" : "{0}.run.append(\"{1}\")",
-           "attributes" : {"name" :
-                           {"variable" : "{0}.run_name[\"{3}\"] = \"{1}\""}}
-          }
-    SASDATA_IDATA_Q = {"variable" : "{0}.x = numpy.append({0}.x, {1})",
-                       "unit" : "x_unit",
-                       "attributes" : {"unit" :
-                                       {"variable" : "{0}.xaxis(\"Q\", \'{1}\')",
-                                        "storeas" : "content"
-                                       }
-                                      },
-                      }
-    SASDATA_IDATA_I = {"variable" : "{0}.y = numpy.append({0}.y, {1})",
-                       "unit" : "y_unit",
-                       "attributes" : {"unit" :
-                                       {"variable" : "{0}.yaxis(\"Intensity\", \'{1}\')",
-                                        "storeas" : "content"
-                                       }
-                                      },
-                      }
-    SASDATA_IDATA_IDEV = {"variable" : "{0}.dy = numpy.append({0}.dy, {1})",
+    RUN = {"attributes" : {"name" :{}}}
+    SASDATA_IDATA_Q = {"units_optional" : False,
+                       "storeas" : "float",
+                        "unit" : "x_unit",
+                       "attributes" : {"unit" : {"storeas" : "content"}},
+                      }
+    SASDATA_IDATA_I = {"units_optional" : False,
+                       "storeas" : "float",
+                        "unit" : "y_unit",
+                       "attributes" : {"unit" : {"storeas" : "content"}},
+                      }
+    SASDATA_IDATA_IDEV = {"units_optional" : False,
+                          "storeas" : "float",
                           "unit" : "y_unit",
-                          "attributes" : {"unit" :
-                                          {"variable" : META_DATA,
-                                           "storeas" : "content"
-                                          }
-                                         },
-                         }
-    SASDATA_IDATA_QDEV = {"variable" : "{0}.dx = numpy.append({0}.dx, {1})",
+                          "attributes" : {"unit" : {"storeas" : "content"}},
+                         }
+    SASDATA_IDATA_QDEV = {"units_optional" : False,
+                          "storeas" : "float",
                           "unit" : "x_unit",
-                          "attributes" : {"unit" :
-                                          {"variable" : META_DATA,
-                                           "storeas" : "content"
-                                          }
-                                         },
-                         }
-    SASDATA_IDATA_DQL = {"variable" : "{0}.dxl = numpy.append({0}.dxl, {1})",
+                          "attributes" : {"unit" : {"storeas" : "content"}},
+                         }
+    SASDATA_IDATA_DQL = {"units_optional" : False,
+                         "storeas" : "float",
                          "unit" : "x_unit",
-                         "attributes" : {"unit" :
-                                         {"variable" : META_DATA,
-                                          "storeas" : "content"
-                                         }
-                                        },
-                        }
-    SASDATA_IDATA_DQW = {"variable" : "{0}.dxw = numpy.append({0}.dxw, {1})",
+                         "attributes" : {"unit" : {"storeas" : "content"}},
+                        }
+    SASDATA_IDATA_DQW = {"units_optional" : False,
+                         "storeas" : "float",
                          "unit" : "x_unit",
-                         "attributes" : {"unit" :
-                                         {"variable" : META_DATA,
-                                          "storeas" : "content"
-                                         }
-                                        },
-                        }
-    SASDATA_IDATA_QMEAN = {"storeas" : "content",
-                           "unit" : "x_unit",
-                           "variable" : META_DATA,
-                           "attributes" : {"unit" : {"variable" : META_DATA}},
+                         "attributes" : {"unit" : {"storeas" : "content"}},
+                        }
+    SASDATA_IDATA_QMEAN = {"unit" : "x_unit",
+                           "attributes" : {"unit" : {}},
                           }
-    SASDATA_IDATA_SHADOWFACTOR = {"variable" : META_DATA,
-                                  "storeas" : "content",
-                                 }
-    SASDATA_IDATA = {"storeas" : "float",
-                     "units_optional" : False,
-                     "variable" : None,
-                     "attributes" : {"name" : {"variable" : META_DATA,
-                                               "storeas" : "content",
-                                              },
-                                     "timestamp" : {"variable" : META_DATA,
-                                                    "storeas" : "timestamp",
-                                                   }
-                                    },
+    SASDATA_IDATA_SHADOWFACTOR = {}
+    SASDATA_IDATA = {"attributes" : {"name" : {},"timestamp" : {"storeas" : "timestamp"}},
                      "children" : {"Q" : SASDATA_IDATA_Q,
                                    "I" : SASDATA_IDATA_I,
@@ -180,5 +130,5 @@
                                   }
                     }
-    SASDATA = {"attributes" : {"name" : {"variable" : META_DATA,}},
+    SASDATA = {"attributes" : {"name" : {}},
                "variable" : None,
                "children" : {"Idata" : SASDATA_IDATA,
@@ -186,36 +136,17 @@
                             }
               }
-    SASTRANSSPEC_TDATA_LAMDBA = {"variable" : "{0}.wavelength.append({1})",
+    SASTRANSSPEC_TDATA_LAMDBA = {"storeas" : "float",
                                  "unit" : "wavelength_unit",
-                                 "attributes" :
-                                 {"unit" :
-                                  {"variable" : "{0}.wavelength_unit = \"{1}\"",
-                                   "storeas" : "content"
-                                  }
-                                 }
+                                 "attributes" : {"unit" : {"storeas" : "content"}}
                                 }
-    SASTRANSSPEC_TDATA_T = {"variable" : "{0}.transmission.append({1})",
+    SASTRANSSPEC_TDATA_T = {"storeas" : "float",
                             "unit" : "transmission_unit",
-                            "attributes" :
-                            {"unit" :
-                             {"variable" : "{0}.transmission_unit = \"{1}\"",
-                              "storeas" : "content"
-                             }
-                            }
-                           }
-    SASTRANSSPEC_TDATA_TDEV = {"variable" :
-                               "{0}.transmission_deviation.append({1})",
+                            "attributes" : {"unit" : {"storeas" : "content"}}
+                           }
+    SASTRANSSPEC_TDATA_TDEV = {"storeas" : "float",
                                "unit" : "transmission_deviation_unit",
-                               "attributes" :
-                               {"unit" :
-                                {"variable" :
-                                 "{0}.transmission_deviation_unit = \"{1}\"",
-                                 "storeas" : "content"
-                                }
-                               }
-                              }
-    SASTRANSSPEC_TDATA = {"storeas" : "float",
-                          "variable" : None,
-                          "children" : {"Lambda" : SASTRANSSPEC_TDATA_LAMDBA,
+                               "attributes" : {"unit" :{"storeas" : "content"}}
+                              }
+    SASTRANSSPEC_TDATA = {"children" : {"Lambda" : SASTRANSSPEC_TDATA_LAMDBA,
                                         "T" : SASTRANSSPEC_TDATA_T,
                                         "Tdev" : SASTRANSSPEC_TDATA_TDEV,
@@ -223,87 +154,50 @@
                                        }
                          }
-    SASTRANSSPEC = {"variable" : None,
-                    "children" : {"Tdata" : SASTRANSSPEC_TDATA,
+    SASTRANSSPEC = {"children" : {"Tdata" : SASTRANSSPEC_TDATA,
                                   "<any>" : ANY,
                                  },
-                    "attributes" :
-                    {"name" :
-                     {"variable" : "{0}.name = \"{1}\""},
-                     "timestamp" :
-                     {"variable" : "{0}.timestamp = \"{1}\""},
-                    }
+                    "attributes" : {"name" :{}, "timestamp" : {},}
                    }
-    SASSAMPLE_THICK = {"variable" : "{0}.sample.thickness = {1}",
-                       "unit" : "sample.thickness_unit",
-                       "storeas" : "float",
-                       "attributes" :
-                       {"unit" :
-                        {"variable" : "{0}.sample.thickness_unit = \"{1}\"",
-                         "storeas" : "content"
-                        }
-                       },
-                      }
-    SASSAMPLE_TRANS = {"variable" : "{0}.sample.transmission = {1}",
-                       "storeas" : "float",
-                      }
-    SASSAMPLE_TEMP = {"variable" : "{0}.sample.temperature = {1}",
-                      "unit" : "sample.temperature_unit",
+    SASSAMPLE_THICK = {"unit" : "thickness_unit",
+                       "storeas" : "float",
+                       "attributes" : {"unit" :{}},
+                      }
+    SASSAMPLE_TRANS = {"storeas" : "float",}
+    SASSAMPLE_TEMP = {"unit" : "temperature_unit",
                       "storeas" : "float",
-                      "attributes" :
-                      {"unit" :
-                       {"variable" : "{0}.sample.temperature_unit = \"{1}\"",
-                        "storeas" : "content"
-                       }
-                      },
+                      "attributes" :{"unit" :{}},
                      }
-    SASSAMPLE_POS_ATTR = {"unit" : {"variable" :
-                                    "{0}.sample.position_unit = \"{1}\"",
-                                    "storeas" : "content"
-                                   }
-                         }
-    SASSAMPLE_POS_X = {"variable" : "{0}.sample.position.x = {1}",
-                       "unit" : "sample.position_unit",
+    SASSAMPLE_POS_ATTR = {"unit" : {}}
+    SASSAMPLE_POS_X = {"unit" : "position_unit",
                        "storeas" : "float",
                        "attributes" : SASSAMPLE_POS_ATTR
                       }
-    SASSAMPLE_POS_Y = {"variable" : "{0}.sample.position.y = {1}",
-                       "unit" : "sample.position_unit",
+    SASSAMPLE_POS_Y = {"unit" : "position_unit",
                        "storeas" : "float",
                        "attributes" : SASSAMPLE_POS_ATTR
                       }
-    SASSAMPLE_POS_Z = {"variable" : "{0}.sample.position.z = {1}",
-                       "unit" : "sample.position_unit",
+    SASSAMPLE_POS_Z = {"unit" : "position_unit",
                        "storeas" : "float",
                        "attributes" : SASSAMPLE_POS_ATTR
                       }
-    SASSAMPLE_POS = {"children" : {"variable" : None,
-                                   "x" : SASSAMPLE_POS_X,
+    SASSAMPLE_POS = {"children" : {"x" : SASSAMPLE_POS_X,
                                    "y" : SASSAMPLE_POS_Y,
                                    "z" : SASSAMPLE_POS_Z,
                                   },
                     }
-    SASSAMPLE_ORIENT_ATTR = {"unit" :
-                             {"variable" :
-                              "{0}.sample.orientation_unit = \"{1}\"",
-                              "storeas" : "content"
-                             }
-                            }
-    SASSAMPLE_ORIENT_ROLL = {"variable" : "{0}.sample.orientation.x = {1}",
-                             "unit" : "sample.orientation_unit",
+    SASSAMPLE_ORIENT_ATTR = {"unit" :{}}
+    SASSAMPLE_ORIENT_ROLL = {"unit" : "orientation_unit",
                              "storeas" : "float",
                              "attributes" : SASSAMPLE_ORIENT_ATTR
                             }
-    SASSAMPLE_ORIENT_PITCH = {"variable" : "{0}.sample.orientation.y = {1}",
-                              "unit" : "sample.orientation_unit",
+    SASSAMPLE_ORIENT_PITCH = {"unit" : "orientation_unit",
                               "storeas" : "float",
                               "attributes" : SASSAMPLE_ORIENT_ATTR
                              }
-    SASSAMPLE_ORIENT_YAW = {"variable" : "{0}.sample.orientation.z = {1}",
-                            "unit" : "sample.orientation_unit",
+    SASSAMPLE_ORIENT_YAW = {"unit" : "orientation_unit",
                             "storeas" : "float",
                             "attributes" : SASSAMPLE_ORIENT_ATTR
                            }
-    SASSAMPLE_ORIENT = {"variable" : None,
-                        "children" : {"roll" : SASSAMPLE_ORIENT_ROLL,
+    SASSAMPLE_ORIENT = {"children" : {"roll" : SASSAMPLE_ORIENT_ROLL,
                                       "pitch" : SASSAMPLE_ORIENT_PITCH,
                                       "yaw" : SASSAMPLE_ORIENT_YAW,
@@ -311,7 +205,6 @@
                        }
     SASSAMPLE = {"attributes" :
-                 {"name" : {"variable" : "{0}.sample.name = \"{1}\""},},
-                 "variable" : None,
-                 "children" : {"ID" : {"variable" : "{0}.sample.ID = \"{1}\""},
+                 {"name" : {},},
+                 "children" : {"ID" : {},
                                "thickness" : SASSAMPLE_THICK,
                                "transmission" : SASSAMPLE_TRANS,
@@ -319,33 +212,22 @@
                                "position" : SASSAMPLE_POS,
                                "orientation" : SASSAMPLE_ORIENT,
-                               "details" :
-                               {"variable" :
-                                "{0}.sample.details.append(\"{1}\")"},
+                               "details" : {},
                                "<any>" : ANY
                               },
                 }
-    SASINSTR_SRC_BEAMSIZE_ATTR = {"unit" :
-                                  "{0}.source.beam_size_unit = \"{1}\"",
-                                  "storeas" : "content"
-                                 }
-    SASINSTR_SRC_BEAMSIZE_X = {"variable" : "{0}.source.beam_size.x = {1}",
-                               "unit" : "source.beam_size_unit",
+    SASINSTR_SRC_BEAMSIZE_ATTR = {"unit" : ""}
+    SASINSTR_SRC_BEAMSIZE_X = {"unit" : "beam_size_unit",
                                "storeas" : "float",
                                "attributes" : SASINSTR_SRC_BEAMSIZE_ATTR
                               }
-    SASINSTR_SRC_BEAMSIZE_Y = {"variable" : "{0}.source.beam_size.y = {1}",
-                               "unit" : "source.beam_size_unit",
+    SASINSTR_SRC_BEAMSIZE_Y = {"unit" : "beam_size_unit",
                                "storeas" : "float",
                                "attributes" : SASINSTR_SRC_BEAMSIZE_ATTR
                               }
-    SASINSTR_SRC_BEAMSIZE_Z = {"variable" : "{0}.source.beam_size.z = {1}",
-                               "unit" : "source.beam_size_unit",
+    SASINSTR_SRC_BEAMSIZE_Z = {"unit" : "beam_size_unit",
                                "storeas" : "float",
                                "attributes" : SASINSTR_SRC_BEAMSIZE_ATTR
                               }
-    SASINSTR_SRC_BEAMSIZE = {"attributes" :
-                             {"name" : {"variable" :
-                                        "{0}.source.beam_size_name = \"{1}\""}},
-                             "variable" : None,
+    SASINSTR_SRC_BEAMSIZE = {"attributes" : {"name" : {}},
                              "children" : {"x" : SASINSTR_SRC_BEAMSIZE_X,
                                            "y" : SASINSTR_SRC_BEAMSIZE_Y,
@@ -353,57 +235,25 @@
                                           }
                             }
-    SASINSTR_SRC_WL = {"variable" : "{0}.source.wavelength = {1}",
-                       "unit" : "source.wavelength_unit",
-                       "storeas" : "float",
-                       "attributes" :
-                       {"unit" :
-                        {"variable" : "{0}.source.wavelength_unit = \"{1}\"",
-                         "storeas" : "content"
-                        },
+    SASINSTR_SRC_WL = {"unit" : "wavelength_unit",
+                       "storeas" : "float",
+                       "attributes" : {"unit" :{},
                        }
                       }
-    SASINSTR_SRC_WL_MIN = {"variable" : "{0}.source.wavelength_min = {1}",
-                           "unit" : "source.wavelength_min_unit",
+    SASINSTR_SRC_WL_MIN = {"unit" : "wavelength_min_unit",
                            "storeas" : "float",
-                           "attributes" :
-                           {"unit" :
-                            {"variable" :
-                             "{0}.source.wavelength_min_unit = \"{1}\"",
-                             "storeas" : "content"
-                            },
-                           }
+                           "attributes" : {"unit" :{"storeas" : "content"},}
                           }
-    SASINSTR_SRC_WL_MAX = {"variable" : "{0}.source.wavelength_max = {1}",
-                           "unit" : "source.wavelength_max_unit",
+    SASINSTR_SRC_WL_MAX = {"unit" : "wavelength_max_unit",
                            "storeas" : "float",
-                           "attributes" :
-                           {"unit" :
-                            {"variable" :
-                             "{0}.source.wavelength_max_unit = \"{1}\"",
-                             "storeas" : "content"
-                            },
-                           }
+                           "attributes" : {"unit" :{"storeas" : "content"},}
                           }
-    SASINSTR_SRC_WL_SPR = {"variable" : "{0}.source.wavelength_spread = {1}",
-                           "unit" : "source.wavelength_spread_unit",
+    SASINSTR_SRC_WL_SPR = {"unit" : "wavelength_spread_unit",
                            "storeas" : "float",
-                           "attributes" :
-                           {"unit" :
-                            {"variable" :
-                             "{0}.source.wavelength_spread_unit = \"{1}\"",
-                             "storeas" : "content"
-                            },
-                           }
+                           "attributes" : {"unit" : {"storeas" : "content"},}
                           }
-    SASINSTR_SRC = {"attributes" : {"name" : {"variable" :
-                                              "{0}.source.name = \"{1}\""}},
-                    "variable" : None,
-                    "children" : {"radiation" :
-                                  {"variable" :
-                                   "{0}.source.radiation = \"{1}\""},
+    SASINSTR_SRC = {"attributes" : {"name" : {}},
+                    "children" : {"radiation" : {},
                                   "beam_size" : SASINSTR_SRC_BEAMSIZE,
-                                  "beam_shape" :
-                                  {"variable" :
-                                   "{0}.source.beam_shape = \"{1}\""},
+                                  "beam_shape" : {},
                                   "wavelength" : SASINSTR_SRC_WL,
                                   "wavelength_min" : SASINSTR_SRC_WL_MIN,
@@ -412,26 +262,18 @@
                                  },
                    }
-    SASINSTR_COLL_APER_ATTR = {"unit" : {"variable" : "{0}.size_unit = \"{1}\"",
-                                         "storeas" : "content"
-                                        },
-                              }
-    SASINSTR_COLL_APER_X = {"variable" : "{0}.size.x = {1}",
-                            "unit" : "size_unit",
+    SASINSTR_COLL_APER_ATTR = {"unit" : {}}
+    SASINSTR_COLL_APER_X = {"unit" : "size_unit",
                             "storeas" : "float",
                             "attributes" : SASINSTR_COLL_APER_ATTR
                            }
-    SASINSTR_COLL_APER_Y = {"variable" : "{0}.size.y = {1}",
-                            "unit" : "size_unit",
+    SASINSTR_COLL_APER_Y = {"unit" : "size_unit",
                             "storeas" : "float",
                             "attributes" : SASINSTR_COLL_APER_ATTR
                            }
-    SASINSTR_COLL_APER_Z = {"variable" : "{0}.size.z = {1}",
-                            "unit" : "size_unit",
+    SASINSTR_COLL_APER_Z = {"unit" : "size_unit",
                             "storeas" : "float",
                             "attributes" : SASINSTR_COLL_APER_ATTR
                            }
-    SASINSTR_COLL_APER_SIZE = {"attributes" :
-                               {"unit" : {"variable" :
-                                          "{0}.size_unit = \"{1}\""}},
+    SASINSTR_COLL_APER_SIZE = {"attributes" : {"unit" : {}},
                                "children" : {"storeas" : "float",
                                              "x" : SASINSTR_COLL_APER_X,
@@ -441,163 +283,101 @@
                               }
     SASINSTR_COLL_APER_DIST = {"storeas" : "float",
-                               "attributes" :
-                               {"storeas" : "content",
-                                "unit" : {"variable" :
-                                          "{0}.distance_unit = \"{1}\""}
-                               },
-                               "variable" : "{0}.distance = {1}",
+                               "attributes" : {"unit" : {}},
                                "unit" : "distance_unit",
                               }
-    SASINSTR_COLL_APER = {"variable" : None,
-                          "attributes" : {"name" : {"variable" :
-                                                    "{0}.name = \"{1}\""},
-                                          "type" : {"variable" :
-                                                    "{0}.type = \"{1}\""},
-                                         },
+    SASINSTR_COLL_APER = {"attributes" : {"name" : {}, "type" : {}, },
                           "children" : {"size" : SASINSTR_COLL_APER_SIZE,
                                         "distance" : SASINSTR_COLL_APER_DIST
                                        }
                          }
-    SASINSTR_COLL = {"attributes" :
-                     {"name" : {"variable" : "{0}.name = \"{1}\""}},
-                     "variable" : None,
+    SASINSTR_COLL = {"attributes" : {"name" : {}},
                      "children" :
-                     {"length" :
-                      {"variable" : "{0}.length = {1}",
-                       "unit" : "length_unit",
-                       "storeas" : "float",
-                       "attributes" :
-                       {"storeas" : "content",
-                        "unit" : {"variable" : "{0}.length_unit = \"{1}\""}
-                       },
-                      },
-                      "aperture" : SASINSTR_COLL_APER,
-                     },
+                         {"length" :
+                          {"unit" : "length_unit",
+                           "storeas" : "float",
+                           "attributes" : {"storeas" : "content", "unit" : {}},
+                          },
+                          "aperture" : SASINSTR_COLL_APER,
+                         },
                     }
-    SASINSTR_DET_SDD = {"variable" : "{0}.distance = {1}",
+    SASINSTR_DET_SDD = {"storeas" : "float",
                         "unit" : "distance_unit",
-                        "attributes" :
-                        {"unit" :
-                         {"variable" : "{0}.distance_unit = \"{1}\"",
-                          "storeas" : "content"
-                         }
-                        },
+                        "attributes" : {"unit" :{}},
                        }
-    SASINSTR_DET_OFF_ATTR = {"unit" : {"variable" : "{0}.offset_unit = \"{1}\"",
-                                       "storeas" : "content"
-                                      },
-                            }
-    SASINSTR_DET_OFF_X = {"variable" : "{0}.offset.x = {1}",
+    SASINSTR_DET_OFF_ATTR = {"unit" : {"storeas" : "content" }}
+    SASINSTR_DET_OFF_X = {"storeas" : "float",
                           "unit" : "offset_unit",
                           "attributes" : SASINSTR_DET_OFF_ATTR
                          }
-    SASINSTR_DET_OFF_Y = {"variable" : "{0}.offset.y = {1}",
+    SASINSTR_DET_OFF_Y = {"storeas" : "float",
                           "unit" : "offset_unit",
                           "attributes" : SASINSTR_DET_OFF_ATTR
                          }
-    SASINSTR_DET_OFF_Z = {"variable" : "{0}.offset.z = {1}",
+    SASINSTR_DET_OFF_Z = {"storeas" : "float",
                           "unit" : "offset_unit",
                           "attributes" : SASINSTR_DET_OFF_ATTR
                          }
-    SASINSTR_DET_OFF = {"variable" : None,
-                        "children" : {"x" : SASINSTR_DET_OFF_X,
+    SASINSTR_DET_OFF = {"children" : {"x" : SASINSTR_DET_OFF_X,
                                       "y" : SASINSTR_DET_OFF_Y,
                                       "z" : SASINSTR_DET_OFF_Z,
                                      }
                        }
-    SASINSTR_DET_OR_ATTR = {"unit" : "{0}.orientation_unit = \"{1}\"",
-                            "storeas" : "content"
-                           }
-    SASINSTR_DET_OR_ROLL = {"variable" : "{0}.orientation.x = {1}",
+    SASINSTR_DET_OR_ATTR = {}
+    SASINSTR_DET_OR_ROLL = {"storeas" : "float",
                             "unit" : "orientation_unit",
                             "attributes" : SASINSTR_DET_OR_ATTR
                            }
-    SASINSTR_DET_OR_PITCH = {"variable" : "{0}.orientation.y = {1}",
+    SASINSTR_DET_OR_PITCH = {"storeas" : "float",
                              "unit" : "orientation_unit",
                              "attributes" : SASINSTR_DET_OR_ATTR
                             }
-    SASINSTR_DET_OR_YAW = {"variable" : "{0}.orientation.z = {1}",
+    SASINSTR_DET_OR_YAW = {"storeas" : "float",
                            "unit" : "orientation_unit",
                            "attributes" : SASINSTR_DET_OR_ATTR
                           }
-    SASINSTR_DET_OR = {"variable" : None,
-                       "children" : {"roll" : SASINSTR_DET_OR_ROLL,
+    SASINSTR_DET_OR = {"children" : {"roll" : SASINSTR_DET_OR_ROLL,
                                      "pitch" : SASINSTR_DET_OR_PITCH,
                                      "yaw" : SASINSTR_DET_OR_YAW,
                                     }
                       }
-    SASINSTR_DET_BC_X = {"variable" : "{0}.beam_center.x = {1}",
+    SASINSTR_DET_BC_X = {"storeas" : "float",
                          "unit" : "beam_center_unit",
-                         "attributes" :
-                         {"unit" : "{0}.beam_center_unit = \"{1}\"",
-                          "storeas" : "content"
-                         }
-                        }
-    SASINSTR_DET_BC_Y = {"variable" : "{0}.beam_center.y = {1}",
+                         "attributes" : {"storeas" : "content"}
+                        }
+    SASINSTR_DET_BC_Y = {"storeas" : "float",
                          "unit" : "beam_center_unit",
-                         "attributes" :
-                         {"unit" : "{0}.beam_center_unit = \"{1}\"",
-                          "storeas" : "content"
-                         }
-                        }
-    SASINSTR_DET_BC_Z = {"variable" : "{0}.beam_center.z = {1}",
+                         "attributes" : {"storeas" : "content"}
+                        }
+    SASINSTR_DET_BC_Z = {"storeas" : "float",
                          "unit" : "beam_center_unit",
-                         "attributes" :
-                         {"unit" : "{0}.beam_center_unit = \"{1}\"",
-                          "storeas" : "content"
-                         }
-                        }
-    SASINSTR_DET_BC = {"variable" : None,
-                       "children" : {"x" : SASINSTR_DET_BC_X,
+                         "attributes" : {"storeas" : "content"}
+                        }
+    SASINSTR_DET_BC = {"children" : {"x" : SASINSTR_DET_BC_X,
                                      "y" : SASINSTR_DET_BC_Y,
-                                     "z" : SASINSTR_DET_BC_Z,
-                                    }
-                      }
-    SASINSTR_DET_PIXEL_X = {"variable" : "{0}.pixel_size.x = {1}",
+                                     "z" : SASINSTR_DET_BC_Z,}
+                      }
+    SASINSTR_DET_PIXEL_X = {"storeas" : "float",
                             "unit" : "pixel_size_unit",
-                            "attributes" :
-                            {"unit" : "{0}.pixel_size_unit = \"{1}\"",
-                             "storeas" : "content"
-                            }
-                           }
-    SASINSTR_DET_PIXEL_Y = {"variable" : "{0}.pixel_size.y = {1}",
+                            "attributes" : {"storeas" : "content" }
+                           }
+    SASINSTR_DET_PIXEL_Y = {"storeas" : "float",
                             "unit" : "pixel_size_unit",
-                            "attributes" :
-                            {"unit" : "{0}.pixel_size_unit = \"{1}\"",
-                             "storeas" : "content"
-                            }
-                           }
-    SASINSTR_DET_PIXEL_Z = {"variable" : "{0}.pixel_size.z = {1}",
+                            "attributes" : {"storeas" : "content"}
+                           }
+    SASINSTR_DET_PIXEL_Z = {"storeas" : "float",
                             "unit" : "pixel_size_unit",
-                            "attributes" :
-                            {"unit" : "{0}.pixel_size_unit = \"{1}\"",
-                             "storeas" : "content"
-                            }
-                           }
-    SASINSTR_DET_PIXEL = {"variable" : None,
-                          "children" : {"x" : SASINSTR_DET_PIXEL_X,
+                            "attributes" : {"storeas" : "content"}
+                           }
+    SASINSTR_DET_PIXEL = {"children" : {"x" : SASINSTR_DET_PIXEL_X,
                                         "y" : SASINSTR_DET_PIXEL_Y,
                                         "z" : SASINSTR_DET_PIXEL_Z,
                                        }
                          }
-    SASINSTR_DET_SLIT = {"variable" : "{0}.slit_length = {1}",
+    SASINSTR_DET_SLIT = {"storeas" : "float",
                          "unit" : "slit_length_unit",
-                         "attributes" :
-                         {"unit" :
-                          {"variable" : "{0}.slit_length_unit = \"{1}\"",
-                           "storeas" : "content"
-                          }
-                         }
-                        }
-    SASINSTR_DET = {"storeas" : "float",
-                    "variable" : None,
-                    "attributes" : {"name" :
-                                    {"storeas" : "content",
-                                     "variable" : "{0}.name = \"{1}\"",
-                                    }
-                                   },
-                    "children" : {"name" : {"storeas" : "content",
-                                            "variable" : "{0}.name = \"{1}\"",
-                                           },
+                         "attributes" : {"unit" : {}}
+                        }
+    SASINSTR_DET = {"attributes" : {"name" : {"storeas" : "content"}},
+                    "children" : {"name" : {"storeas" : "content"},
                                   "SDD" : SASINSTR_DET_SDD,
                                   "offset" : SASINSTR_DET_OFF,
@@ -608,8 +388,6 @@
                                  }
                    }
-    SASINSTR = {"variable" : None,
-                "children" :
-                {"variable" : None,
-                 "name" : {"variable" : "{0}.instrument = \"{1}\""},
+    SASINSTR = {"children" :
+                {"name" : {},
                  "SASsource" : SASINSTR_SRC,
                  "SAScollimation" : SASINSTR_COLL,
@@ -619,9 +397,6 @@
     CANSAS_FORMAT = {"SASentry" :
                      {"units_optional" : True,
-                      "variable" : None,
                       "storeas" : "content",
-                      "attributes" : {"name" :
-                                      {"variable" :
-                                       "{0}.run_name[\"{3}\"] = \"{1}\""}},
+                      "attributes" : {"name" : {}},
                       "children" : {"Title" : TITLE,
                                     "Run" : RUN,
@@ -644,5 +419,4 @@
 
     current_level = ''
-    ns_variable = ''
     ns_datatype = ''
     ns_optional = True
@@ -650,5 +424,4 @@
     def __init__(self):
         self.current_level = {}
-        self.ns_variable = ''
         self.ns_datatype = "content"
         self.ns_optional = True
Index: src/sas/sascalc/dataloader/readers/cansas_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision 83b6408fbfaefa4819b955c697fef834d8f033f6)
+++ src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision 250fec92ea66b0770da33360a90f022e1d674072)
@@ -14,5 +14,5 @@
 
 import logging
-import numpy
+import numpy as np
 import os
 import sys
@@ -20,13 +20,10 @@
 import inspect
 # For saving individual sections of data
-from sas.sascalc.dataloader.data_info import Data1D
-from sas.sascalc.dataloader.data_info import Collimation
-from sas.sascalc.dataloader.data_info import TransmissionSpectrum
-from sas.sascalc.dataloader.data_info import Detector
-from sas.sascalc.dataloader.data_info import Process
-from sas.sascalc.dataloader.data_info import Aperture
+from sas.sascalc.dataloader.data_info import Data1D, DataInfo, plottable_1D
+from sas.sascalc.dataloader.data_info import Collimation, TransmissionSpectrum, Detector, Process, Aperture
+from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable as combine_data
 import sas.sascalc.dataloader.readers.xml_reader as xml_reader
 from sas.sascalc.dataloader.readers.xml_reader import XMLreader
-from sas.sascalc.dataloader.readers.cansas_constants import CansasConstants
+from sas.sascalc.dataloader.readers.cansas_constants import CansasConstants, CurrentLevel
 
 # The following 2 imports *ARE* used. Do not remove either.
@@ -34,11 +31,11 @@
 from xml.dom.minidom import parseString
 
-## TODO: Refactor to load multiple <SASData> as separate Data1D objects
-## TODO: Refactor to allow invalid XML, but give a useful warning when loaded
-
-_ZERO = 1e-16
 PREPROCESS = "xmlpreprocess"
 ENCODING = "encoding"
 RUN_NAME_DEFAULT = "None"
+INVALID_SCHEMA_PATH_1_1 = "{0}/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_1.xsd"
+INVALID_SCHEMA_PATH_1_0 = "{0}/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_0.xsd"
+INVALID_XML = "\n\nThe loaded xml file, {0} does not fully meet the CanSAS v1.x specification. SasView loaded " + \
+              "as much of the data as possible.\n\n"
 HAS_CONVERTER = True
 try:
@@ -52,46 +49,4 @@
 ALLOW_ALL = True
 
-# DO NOT REMOVE Called by outside packages:
-#    sas.sasgui.perspectives.invariant.invariant_state
-#    sas.sasgui.perspectives.fitting.pagestate
-def get_content(location, node):
-    """
-    Get the first instance of the content of a xpath location.
-
-    :param location: xpath location
-    :param node: node to start at
-
-    :return: Element, or None
-    """
-    nodes = node.xpath(location,
-                       namespaces={'ns': CANSAS_NS.get("1.0").get("ns")})
-    if len(nodes) > 0:
-        return nodes[0]
-    else:
-        return None
-
-# DO NOT REMOVE Called by outside packages:
-#    sas.sasgui.perspectives.fitting.pagestate
-def write_node(doc, parent, name, value, attr=None):
-    """
-    :param doc: document DOM
-    :param parent: parent node
-    :param name: tag of the element
-    :param value: value of the child text node
-    :param attr: attribute dictionary
-
-    :return: True if something was appended, otherwise False
-    """
-    if attr is None:
-        attr = {}
-    if value is not None:
-        node = doc.createElement(name)
-        node.appendChild(doc.createTextNode(str(value)))
-        for item in attr:
-            node.setAttribute(item, attr[item])
-        parent.appendChild(node)
-        return True
-    return False
-
 class Reader(XMLreader):
     """
@@ -101,10 +56,23 @@
         The CanSAS reader requires PyXML 0.8.4 or later.
     """
-    ##CanSAS version - defaults to version 1.0
+    ## CanSAS version - defaults to version 1.0
     cansas_version = "1.0"
     base_ns = "{cansas1d/1.0}"
+    cansas_defaults = None
+    type_name = "canSAS"
+    invalid = True
+    ## Log messages and errors
     logging = None
-    errors = None
-    type_name = "canSAS"
+    errors = set()
+    ## Namespace hierarchy for current xml_file object
+    names = None
+    ns_list = None
+    ## Temporary storage location for loading multiple data sets in a single file
+    current_datainfo = None
+    current_dataset = None
+    current_data1d = None
+    data = None
+    ## List of data1D objects to be sent back to SasView
+    output = None
     ## Wildcards
     type = ["XML files (*.xml)|*.xml", "SasView Save Files (*.svs)|*.svs"]
@@ -114,9 +82,332 @@
     allow_all = True
 
-    def __init__(self):
-        ## List of errors
-        self.errors = set()
+    def reset_state(self):
+        """
+        Resets the class state to a base case when loading a new data file so previous
+        data files do not appear a second time
+        """
+        self.current_datainfo = None
+        self.current_dataset = None
+        self.current_data1d = None
+        self.data = []
+        self.process = Process()
+        self.transspectrum = TransmissionSpectrum()
+        self.aperture = Aperture()
+        self.collimation = Collimation()
+        self.detector = Detector()
+        self.names = []
+        self.cansas_defaults = {}
+        self.output = []
+        self.ns_list = None
         self.logging = []
         self.encoding = None
+
+    def read(self, xml_file, schema_path="", invalid=True):
+        """
+        Validate and read in an xml_file file in the canSAS format.
+
+        :param xml_file: A canSAS file path in proper XML format
+        :param schema_path: A file path to an XML schema to validate the xml_file against
+        """
+        # For every file loaded, reset everything to a base state
+        self.reset_state()
+        self.invalid = invalid
+        # Check that the file exists
+        if os.path.isfile(xml_file):
+            basename, extension = os.path.splitext(os.path.basename(xml_file))
+            # If the file type is not allowed, return nothing
+            if extension in self.ext or self.allow_all:
+                # Get the file location of
+                self.load_file_and_schema(xml_file, schema_path)
+                self.add_data_set()
+                # Try to load the file, but raise an error if unable to.
+                # Check the file matches the XML schema
+                try:
+                    self.is_cansas(extension)
+                    self.invalid = False
+                    # Get each SASentry from XML file and add it to a list.
+                    entry_list = self.xmlroot.xpath(
+                            '/ns:SASroot/ns:SASentry',
+                            namespaces={'ns': self.cansas_defaults.get("ns")})
+                    self.names.append("SASentry")
+
+                    # Get all preprocessing events and encoding
+                    self.set_processing_instructions()
+
+                    # Parse each <SASentry> item
+                    for entry in entry_list:
+                        # Create a new DataInfo object for every <SASentry>
+
+
+                        # Set the file name and then parse the entry.
+                        self.current_datainfo.filename = basename + extension
+                        self.current_datainfo.meta_data["loader"] = "CanSAS XML 1D"
+                        self.current_datainfo.meta_data[PREPROCESS] = \
+                            self.processing_instructions
+
+                        # Parse the XML SASentry
+                        self._parse_entry(entry)
+                        # Combine datasets with datainfo
+                        self.add_data_set()
+                except RuntimeError:
+                    # If the file does not match the schema, raise this error
+                    invalid_xml = self.find_invalid_xml()
+                    invalid_xml = INVALID_XML.format(basename + extension) + invalid_xml
+                    self.errors.add(invalid_xml)
+                    # Try again with an invalid CanSAS schema, that requires only a data set in each
+                    base_name = xml_reader.__file__
+                    base_name = base_name.replace("\\", "/")
+                    base = base_name.split("/sas/")[0]
+                    if self.cansas_version == "1.1":
+                        invalid_schema = INVALID_SCHEMA_PATH_1_1.format(base, self.cansas_defaults.get("schema"))
+                    else:
+                        invalid_schema = INVALID_SCHEMA_PATH_1_0.format(base, self.cansas_defaults.get("schema"))
+                    self.set_schema(invalid_schema)
+                    try:
+                        if self.invalid:
+                            if self.is_cansas():
+                                self.output = self.read(xml_file, invalid_schema, False)
+                            else:
+                                raise RuntimeError
+                        else:
+                            raise RuntimeError
+                    except RuntimeError:
+                        x = np.zeros(1)
+                        y = np.zeros(1)
+                        self.current_data1d = Data1D(x,y)
+                        self.current_data1d.errors = self.errors
+                        return [self.current_data1d]
+        else:
+            self.output.append("Not a valid file path.")
+        # Return a list of parsed entries that dataloader can manage
+        return self.output
+
+    def _parse_entry(self, dom):
+        """
+        Parse a SASEntry - new recursive method for parsing the dom of
+            the CanSAS data format. This will allow multiple data files
+            and extra nodes to be read in simultaneously.
+
+        :param dom: dom object with a namespace base of names
+        """
+
+        self._check_for_empty_data()
+        self.base_ns = "{0}{1}{2}".format("{", \
+                            CANSAS_NS.get(self.cansas_version).get("ns"), "}")
+        tagname = ''
+        tagname_original = ''
+
+        # Go through each child in the parent element
+        for node in dom:
+            # Get the element name and set the current names level
+            tagname = node.tag.replace(self.base_ns, "")
+            tagname_original = tagname
+            # Skip this iteration when loading in save state information
+            if tagname == "fitting_plug_in" or tagname == "pr_inversion" or tagname == "invariant":
+                continue
+
+            # Get where to store content
+            self.names.append(tagname_original)
+            self.ns_list = CONSTANTS.iterate_namespace(self.names)
+            # If the element is a child element, recurse
+            if len(node.getchildren()) > 0:
+                self.parent_class = tagname_original
+                if tagname == 'SASdata':
+                    self._initialize_new_data_set()
+                ## Recursion step to access data within the group
+                self._parse_entry(node)
+                self.add_intermediate()
+            else:
+                data_point, unit = self._get_node_value(node, tagname)
+
+                ## If this is a dataset, store the data appropriately
+                if tagname == 'Run':
+                    self.current_datainfo.run.append(data_point)
+                elif tagname == 'Title':
+                    self.current_datainfo.title = data_point
+                elif tagname == 'SASnote':
+                    self.current_datainfo.notes.append(data_point)
+
+                ## I and Q Data
+                elif tagname == 'I':
+                    self.current_dataset.yaxis("Intensity", unit)
+                    self.current_dataset.y = np.append(self.current_dataset.y, data_point)
+                elif tagname == 'Idev':
+                    self.current_dataset.dy = np.append(self.current_dataset.dy, data_point)
+                elif tagname == 'Q':
+                    self.current_dataset.xaxis("Q", unit)
+                    self.current_dataset.x = np.append(self.current_dataset.x, data_point)
+                elif tagname == 'Qdev':
+                    self.current_dataset.dx = np.append(self.current_dataset.dx, data_point)
+                elif tagname == 'dQw':
+                    self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point)
+                elif tagname == 'dQl':
+                    self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point)
+
+                ## Sample Information
+                elif tagname == 'ID' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.ID = data_point
+                elif tagname == 'Title' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.name = data_point
+                elif tagname == 'thickness' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.thickness = data_point
+                    self.current_datainfo.sample.thickness_unit = unit
+                elif tagname == 'transmission' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.transmission = data_point
+                elif tagname == 'temperature' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.temperature = data_point
+                    self.current_datainfo.sample.temperature_unit = unit
+                elif tagname == 'details' and self.parent_class == 'SASsample':
+                    self.current_datainfo.sample.details.append(data_point)
+                elif tagname == 'x' and self.parent_class == 'position':
+                    self.current_datainfo.sample.position.x = data_point
+                    self.current_datainfo.sample.position_unit = unit
+                elif tagname == 'y' and self.parent_class == 'position':
+                    self.current_datainfo.sample.position.y = data_point
+                    self.current_datainfo.sample.position_unit = unit
+                elif tagname == 'z' and self.parent_class == 'position':
+                    self.current_datainfo.sample.position.z = data_point
+                    self.current_datainfo.sample.position_unit = unit
+                elif tagname == 'roll' and self.parent_class == 'orientation' and 'SASsample' in self.names:
+                    self.current_datainfo.sample.orientation.x = data_point
+                    self.current_datainfo.sample.orientation_unit = unit
+                elif tagname == 'pitch' and self.parent_class == 'orientation' and 'SASsample' in self.names:
+                    self.current_datainfo.sample.orientation.y = data_point
+                    self.current_datainfo.sample.orientation_unit = unit
+                elif tagname == 'yaw' and self.parent_class == 'orientation' and 'SASsample' in self.names:
+                    self.current_datainfo.sample.orientation.z = data_point
+                    self.current_datainfo.sample.orientation_unit = unit
+
+                ## Instrumental Information
+                elif tagname == 'name' and self.parent_class == 'SASinstrument':
+                    self.current_datainfo.instrument = data_point
+                ## Detector Information
+                elif tagname == 'name' and self.parent_class == 'SASdetector':
+                    self.detector.name = data_point
+                elif tagname == 'SDD' and self.parent_class == 'SASdetector':
+                    self.detector.distance = data_point
+                    self.detector.distance_unit = unit
+                elif tagname == 'slit_length' and self.parent_class == 'SASdetector':
+                    self.detector.slit_length = data_point
+                    self.detector.slit_length_unit = unit
+                elif tagname == 'x' and self.parent_class == 'offset':
+                    self.detector.offset.x = data_point
+                    self.detector.offset_unit = unit
+                elif tagname == 'y' and self.parent_class == 'offset':
+                    self.detector.offset.y = data_point
+                    self.detector.offset_unit = unit
+                elif tagname == 'z' and self.parent_class == 'offset':
+                    self.detector.offset.z = data_point
+                    self.detector.offset_unit = unit
+                elif tagname == 'x' and self.parent_class == 'beam_center':
+                    self.detector.beam_center.x = data_point
+                    self.detector.beam_center_unit = unit
+                elif tagname == 'y' and self.parent_class == 'beam_center':
+                    self.detector.beam_center.y = data_point
+                    self.detector.beam_center_unit = unit
+                elif tagname == 'z' and self.parent_class == 'beam_center':
+                    self.detector.beam_center.z = data_point
+                    self.detector.beam_center_unit = unit
+                elif tagname == 'x' and self.parent_class == 'pixel_size':
+                    self.detector.pixel_size.x = data_point
+                    self.detector.pixel_size_unit = unit
+                elif tagname == 'y' and self.parent_class == 'pixel_size':
+                    self.detector.pixel_size.y = data_point
+                    self.detector.pixel_size_unit = unit
+                elif tagname == 'z' and self.parent_class == 'pixel_size':
+                    self.detector.pixel_size.z = data_point
+                    self.detector.pixel_size_unit = unit
+                elif tagname == 'roll' and self.parent_class == 'orientation' and 'SASdetector' in self.names:
+                    self.detector.orientation.x = data_point
+                    self.detector.orientation_unit = unit
+                elif tagname == 'pitch' and self.parent_class == 'orientation' and 'SASdetector' in self.names:
+                    self.detector.orientation.y = data_point
+                    self.detector.orientation_unit = unit
+                elif tagname == 'yaw' and self.parent_class == 'orientation' and 'SASdetector' in self.names:
+                    self.detector.orientation.z = data_point
+                    self.detector.orientation_unit = unit
+                ## Collimation and Aperture
+                elif tagname == 'length' and self.parent_class == 'SAScollimation':
+                    self.collimation.length = data_point
+                    self.collimation.length_unit = unit
+                elif tagname == 'name' and self.parent_class == 'SAScollimation':
+                    self.collimation.name = data_point
+                elif tagname == 'distance' and self.parent_class == 'aperture':
+                    self.aperture.distance = data_point
+                    self.aperture.distance_unit = unit
+                elif tagname == 'x' and self.parent_class == 'size':
+                    self.aperture.size.x = data_point
+                    self.collimation.size_unit = unit
+                elif tagname == 'y' and self.parent_class == 'size':
+                    self.aperture.size.y = data_point
+                    self.collimation.size_unit = unit
+                elif tagname == 'z' and self.parent_class == 'size':
+                    self.aperture.size.z = data_point
+                    self.collimation.size_unit = unit
+
+                ## Process Information
+                elif tagname == 'name' and self.parent_class == 'SASprocess':
+                    self.process.name = data_point
+                elif tagname == 'description' and self.parent_class == 'SASprocess':
+                    self.process.description = data_point
+                elif tagname == 'date' and self.parent_class == 'SASprocess':
+                    try:
+                        self.process.date = datetime.datetime.fromtimestamp(data_point)
+                    except:
+                        self.process.date = data_point
+                elif tagname == 'SASprocessnote':
+                    self.process.notes.append(data_point)
+                elif tagname == 'term' and self.parent_class == 'SASprocess':
+                    self.process.term.append(data_point)
+
+                ## Transmission Spectrum
+                elif tagname == 'T' and self.parent_class == 'Tdata':
+                    self.transspectrum.transmission = np.append(self.transspectrum.transmission, data_point)
+                    self.transspectrum.transmission_unit = unit
+                elif tagname == 'Tdev' and self.parent_class == 'Tdata':
+                    self.transspectrum.transmission_deviation = np.append(self.transspectrum.transmission_deviation, data_point)
+                    self.transspectrum.transmission_deviation_unit = unit
+                elif tagname == 'Lambda' and self.parent_class == 'Tdata':
+                    self.transspectrum.wavelength = np.append(self.transspectrum.wavelength, data_point)
+                    self.transspectrum.wavelength_unit = unit
+
+                ## Source Information
+                elif tagname == 'wavelength' and (self.parent_class == 'SASsource' or self.parent_class == 'SASData'):
+                    self.current_datainfo.source.wavelength = data_point
+                    self.current_datainfo.source.wavelength_unit = unit
+                elif tagname == 'wavelength_min' and self.parent_class == 'SASsource':
+                    self.current_datainfo.source.wavelength_min = data_point
+                    self.current_datainfo.source.wavelength_min_unit = unit
+                elif tagname == 'wavelength_max' and self.parent_class == 'SASsource':
+                    self.current_datainfo.source.wavelength_max = data_point
+                    self.current_datainfo.source.wavelength_max_unit = unit
+                elif tagname == 'wavelength_spread' and self.parent_class == 'SASsource':
+                    self.current_datainfo.source.wavelength_spread = data_point
+                    self.current_datainfo.source.wavelength_spread_unit = unit
+                elif tagname == 'x' and self.parent_class == 'beam_size':
+                    self.current_datainfo.source.beam_size.x = data_point
+                    self.current_datainfo.source.beam_size_unit = unit
+                elif tagname == 'y' and self.parent_class == 'beam_size':
+                    self.current_datainfo.source.beam_size.y = data_point
+                    self.current_datainfo.source.beam_size_unit = unit
+                elif tagname == 'z' and self.parent_class == 'pixel_size':
+                    self.current_datainfo.source.data_point.z = data_point
+                    self.current_datainfo.source.beam_size_unit = unit
+                elif tagname == 'radiation' and self.parent_class == 'SASsource':
+                    self.current_datainfo.source.radiation = data_point
+                elif tagname == 'beam_shape' and self.parent_class == 'SASsource':
+                    self.current_datainfo.source.beam_shape = data_point
+
+                ## Everything else goes in meta_data
+                else:
+                    new_key = self._create_unique_key(self.current_datainfo.meta_data, tagname)
+                    self.current_datainfo.meta_data[new_key] = data_point
+
+            self.names.remove(tagname_original)
+            length = 0
+            if len(self.names) > 1:
+                length = len(self.names) - 1
+            self.parent_class = self.names[length]
+
 
     def is_cansas(self, ext="xml"):
@@ -134,11 +425,12 @@
         if ext == "svs":
             return True
-        return False
+        raise RuntimeError
 
     def load_file_and_schema(self, xml_file, schema_path=""):
         """
-        Loads the file and associates a schema, if a known schema exists
+        Loads the file and associates a schema, if a schema is passed in or if one already exists
 
         :param xml_file: The xml file path sent to Reader.read
+        :param schema_path: The path to a schema associated with the xml_file, or find one based on the file
         """
         base_name = xml_reader.__file__
@@ -151,135 +443,112 @@
 
         # Generic values for the cansas file based on the version
-        cansas_defaults = CANSAS_NS.get(self.cansas_version, "1.0")
+        self.cansas_defaults = CANSAS_NS.get(self.cansas_version, "1.0")
         if schema_path == "":
-            schema_path = "{0}/sas/sascalc/dataloader/readers/schema/{1}".format\
-                (base, cansas_defaults.get("schema")).replace("\\", "/")
+            schema_path = "{0}/sas/sascalc/dataloader/readers/schema/{1}".format \
+                (base, self.cansas_defaults.get("schema")).replace("\\", "/")
 
         # Link a schema to the XML file.
         self.set_schema(schema_path)
-        return cansas_defaults
-
-    ## TODO: Test loading invalid CanSAS XML files and see if this works
-    ## TODO: Once works, try adding a warning that the data is invalid
-    def read(self, xml_file, schema_path=""):
-        """
-        Validate and read in an xml_file file in the canSAS format.
-
-        :param xml_file: A canSAS file path in proper XML format
-        """
-        # output - Final list of Data1D objects
-        output = []
-        # ns - Namespace hierarchy for current xml_file object
-        ns_list = []
-
-        # Check that the file exists
-        if os.path.isfile(xml_file):
-            basename = os.path.basename(xml_file)
-            _, extension = os.path.splitext(basename)
-            # If the file type is not allowed, return nothing
-            if extension in self.ext or self.allow_all:
-                # Get the file location of
-                cansas_defaults = self.load_file_and_schema(xml_file, schema_path)
-
-                # Try to load the file, but raise an error if unable to.
-                # Check the file matches the XML schema
-                try:
-                    if self.is_cansas(extension):
-                        # Get each SASentry from XML file and add it to a list.
-                        entry_list = self.xmlroot.xpath(
-                                '/ns:SASroot/ns:SASentry',
-                                namespaces={'ns': cansas_defaults.get("ns")})
-                        ns_list.append("SASentry")
-
-                        # If multiple files, modify the name for each is unique
-                        increment = 0
-                        # Parse each SASentry item
-                        for entry in entry_list:
-                            # Define a new Data1D object with zeroes for
-                            # x_vals and y_vals
-                            data1d = Data1D(numpy.empty(0), numpy.empty(0),
-                                            numpy.empty(0), numpy.empty(0))
-                            data1d.dxl = numpy.empty(0)
-                            data1d.dxw = numpy.empty(0)
-
-                            # If more than one SASentry, increment each in order
-                            name = basename
-                            if len(entry_list) - 1 > 0:
-                                name += "_{0}".format(increment)
-                                increment += 1
-
-                            # Set the Data1D name and then parse the entry.
-                            # The entry is appended to a list of entry values
-                            data1d.filename = name
-                            data1d.meta_data["loader"] = "CanSAS 1D"
-
-                            # Get all preprocessing events and encoding
-                            self.set_processing_instructions()
-                            data1d.meta_data[PREPROCESS] = \
-                                    self.processing_instructions
-
-                            # Parse the XML file
-                            return_value, extras = \
-                                self._parse_entry(entry, ns_list, data1d)
-                            del extras[:]
-
-                            return_value = self._final_cleanup(return_value)
-                            output.append(return_value)
-                    else:
-                        raise RuntimeError, "Invalid XML at: {0}".format(\
-                                                    self.find_invalid_xml())
-                except:
-                    # If the file does not match the schema, raise this error
-                    schema_path = "{0}/sas/sascalc/dataloader/readers/schema/cansas1d_invalid.xsd"
-                    invalid_xml = self.find_invalid_xml()
-                    invalid_xml = "\n\nThe loaded xml file does not fully meet the CanSAS v1.x specification. SasView " + \
-                                  "loaded as much of the data as possible.\n\n" + invalid_xml
-                    self.errors.add(invalid_xml)
-                    self.set_schema(schema_path)
-                    if self.is_cansas():
-                        output = self.read(xml_file, schema_path)
-                    else:
-                        raise RuntimeError, "%s cannot be read" % xml_file
-                return output
-        # Return a list of parsed entries that dataloader can manage
-        return None
-
-    def _final_cleanup(self, data1d):
+
+    def add_data_set(self):
+        """
+        Adds the current_dataset to the list of outputs after preforming final processing on the data and then calls a
+        private method to generate a new data set.
+
+        :param key: NeXus group name for current tree level
+        """
+
+        if self.current_datainfo and self.current_dataset:
+            self._final_cleanup()
+        self.data = []
+        self.current_datainfo = DataInfo()
+
+    def _initialize_new_data_set(self, parent_list=None):
+        """
+        A private class method to generate a new 1D data object.
+        Outside methods should call add_data_set() to be sure any existing data is stored properly.
+
+        :param parent_list: List of names of parent elements
+        """
+
+        if parent_list is None:
+            parent_list = []
+        x = np.array(0)
+        y = np.array(0)
+        self.current_dataset = plottable_1D(x, y)
+
+    def add_intermediate(self):
+        """
+        This method stores any intermediate objects within the final data set after fully reading the set.
+
+        :param parent: The NXclass name for the h5py Group object that just finished being processed
+        """
+
+        if self.parent_class == 'SASprocess':
+            self.current_datainfo.process.append(self.process)
+            self.process = Process()
+        elif self.parent_class == 'SASdetector':
+            self.current_datainfo.detector.append(self.detector)
+            self.detector = Detector()
+        elif self.parent_class == 'SAStransmission_spectrum':
+            self.current_datainfo.trans_spectrum.append(self.transspectrum)
+            self.transspectrum = TransmissionSpectrum()
+        elif self.parent_class == 'SAScollimation':
+            self.current_datainfo.collimation.append(self.collimation)
+            self.collimation = Collimation()
+        elif self.parent_class == 'SASaperture':
+            self.collimation.aperture.append(self.aperture)
+            self.aperture = Aperture()
+        elif self.parent_class == 'SASdata':
+            self._check_for_empty_resolution()
+            self.data.append(self.current_dataset)
+
+    def _final_cleanup(self):
         """
         Final cleanup of the Data1D object to be sure it has all the
         appropriate information needed for perspectives
-
-        :param data1d: Data1D object that has been populated
-        """
-        # Final cleanup
-        # Remove empty nodes, verify array sizes are correct
+        """
+
+        ## Append errors to dataset and reset class errors
+        self.current_datainfo.errors = set()
         for error in self.errors:
-            data1d.errors.append(error)
+            self.current_datainfo.errors.add(error)
         self.errors.clear()
-        numpy.trim_zeros(data1d.x)
-        numpy.trim_zeros(data1d.y)
-        numpy.trim_zeros(data1d.dy)
-        size_dx = data1d.dx.size
-        size_dxl = data1d.dxl.size
-        size_dxw = data1d.dxw.size
-        if data1d._xunit != data1d.x_unit:
-            data1d.x_unit = data1d._xunit
-        if data1d._yunit != data1d.y_unit:
-            data1d.y_unit = data1d._yunit
-        if size_dxl == 0 and size_dxw == 0:
-            data1d.dxl = None
-            data1d.dxw = None
-            numpy.trim_zeros(data1d.dx)
-        elif size_dx == 0:
-            data1d.dx = None
-            size_dx = size_dxl
-            numpy.trim_zeros(data1d.dxl)
-            numpy.trim_zeros(data1d.dxw)
-        return data1d
+
+        ## Combine all plottables with datainfo and append each to output
+        ## Type cast data arrays to float64 and find min/max as appropriate
+        for dataset in self.data:
+            if dataset.x is not None:
+                dataset.x = np.delete(dataset.x, [0])
+                dataset.x = dataset.x.astype(np.float64)
+                dataset.xmin = np.min(dataset.x)
+                dataset.xmax = np.max(dataset.x)
+            if dataset.y is not None:
+                dataset.y = np.delete(dataset.y, [0])
+                dataset.y = dataset.y.astype(np.float64)
+                dataset.ymin = np.min(dataset.y)
+                dataset.ymax = np.max(dataset.y)
+            if dataset.dx is not None:
+                dataset.dx = np.delete(dataset.dx, [0])
+                dataset.dx = dataset.dx.astype(np.float64)
+            if dataset.dxl is not None:
+                dataset.dxl = np.delete(dataset.dxl, [0])
+                dataset.dxl = dataset.dxl.astype(np.float64)
+            if dataset.dxw is not None:
+                dataset.dxw = np.delete(dataset.dxw, [0])
+                dataset.dxw = dataset.dxw.astype(np.float64)
+            if dataset.dy is not None:
+                dataset.dy = np.delete(dataset.dy, [0])
+                dataset.dy = dataset.dy.astype(np.float64)
+            np.trim_zeros(dataset.x)
+            np.trim_zeros(dataset.y)
+            np.trim_zeros(dataset.dy)
+            final_dataset = combine_data(dataset, self.current_datainfo)
+            self.output.append(final_dataset)
 
     def _create_unique_key(self, dictionary, name, numb=0):
         """
         Create a unique key value for any dictionary to prevent overwriting
-        Recurses until a unique key value is found.
+        Recurse until a unique key value is found.
 
         :param dictionary: A dictionary with any number of entries
@@ -294,14 +563,47 @@
         return name
 
-    def _unit_conversion(self, node, new_current_level, data1d, \
-                                                tagname, node_value):
+    def _get_node_value(self, node, tagname):
+        """
+        Get the value of a node and any applicable units
+
+        :param node: The XML node to get the value of
+        :param tagname: The tagname of the node
+        """
+        #Get the text from the node and convert all whitespace to spaces
+        units = ''
+        node_value = node.text
+        if node_value is not None:
+            node_value = ' '.join(node_value.split())
+        else:
+            node_value = ""
+
+        # If the value is a float, compile with units.
+        if self.ns_list.ns_datatype == "float":
+            # If an empty value is given, set as zero.
+            if node_value is None or node_value.isspace() \
+                                    or node_value.lower() == "nan":
+                node_value = "0.0"
+            #Convert the value to the base units
+            node_value, units = self._unit_conversion(node, tagname, node_value)
+
+        # If the value is a timestamp, convert to a datetime object
+        elif self.ns_list.ns_datatype == "timestamp":
+            if node_value is None or node_value.isspace():
+                pass
+            else:
+                try:
+                    node_value = \
+                        datetime.datetime.fromtimestamp(node_value)
+                except ValueError:
+                    node_value = None
+        return node_value, units
+
+    def _unit_conversion(self, node, tagname, node_value):
         """
         A unit converter method used to convert the data included in the file
         to the default units listed in data_info
 
-        :param new_current_level: cansas_constants level as returned by
-            iterate_namespace
-        :param attr: The attributes of the node
-        :param data1d: Where the values will be saved
+        :param node: XML node
+        :param tagname: name of the node
         :param node_value: The value of the current dom node
         """
@@ -310,13 +612,33 @@
         err_msg = None
         default_unit = None
-        if 'unit' in attr and new_current_level.get('unit') is not None:
+        if 'unit' in attr and attr.get('unit') is not None and not self.ns_list.ns_optional:
             try:
                 local_unit = attr['unit']
-                if isinstance(node_value, float) is False:
-                    exec("node_value = float({0})".format(node_value))
-                unitname = new_current_level.get("unit")
-                exec "default_unit = data1d.{0}".format(unitname)
-                if local_unit is not None and default_unit is not None and \
-                        local_unit.lower() != default_unit.lower() \
+                if not isinstance(node_value, float):
+                    node_value = float(node_value)
+                unitname = self.ns_list.current_level.get("unit", "")
+                if "SASdetector" in self.names:
+                    save_in = "detector"
+                elif "aperture" in self.names:
+                    save_in = "aperture"
+                elif "SAScollimation" in self.names:
+                    save_in = "collimation"
+                elif "SAStransmission_spectrum" in self.names:
+                    save_in = "transspectrum"
+                elif "SASdata" in self.names:
+                    x = np.zeros(1)
+                    y = np.zeros(1)
+                    self.current_data1d = Data1D(x, y)
+                    save_in = "current_data1d"
+                elif "SASsource" in self.names:
+                    save_in = "current_datainfo.source"
+                elif "SASsample" in self.names:
+                    save_in = "current_datainfo.sample"
+                elif "SASprocess" in self.names:
+                    save_in = "process"
+                else:
+                    save_in = "current_datainfo"
+                exec "default_unit = self.{0}.{1}".format(save_in, unitname)
+                if local_unit and default_unit and local_unit.lower() != default_unit.lower() \
                         and local_unit.lower() != "none":
                     if HAS_CONVERTER == True:
@@ -345,8 +667,7 @@
         if err_msg:
             self.errors.add(err_msg)
-        node_value = "float({0})".format(node_value)
         return node_value, value_unit
 
-    def _check_for_empty_data(self, data1d):
+    def _check_for_empty_data(self):
         """
         Creates an empty data set if no data is passed to the reader
@@ -354,51 +675,16 @@
         :param data1d: presumably a Data1D object
         """
-        if data1d == None:
-            self.errors = set()
-            x_vals = numpy.empty(0)
-            y_vals = numpy.empty(0)
-            dx_vals = numpy.empty(0)
-            dy_vals = numpy.empty(0)
-            dxl = numpy.empty(0)
-            dxw = numpy.empty(0)
-            data1d = Data1D(x_vals, y_vals, dx_vals, dy_vals)
-            data1d.dxl = dxl
-            data1d.dxw = dxw
-        return data1d
-
-    def _handle_special_cases(self, tagname, data1d, children):
-        """
-        Handle cases where the data type in Data1D is a dictionary or list
-
-        :param tagname: XML tagname in use
-        :param data1d: The original Data1D object
-        :param children: Child nodes of node
-        :param node: existing node with tag name 'tagname'
-        """
-        if tagname == "SASdetector":
-            data1d = Detector()
-        elif tagname == "SAScollimation":
-            data1d = Collimation()
-        elif tagname == "SAStransmission_spectrum":
-            data1d = TransmissionSpectrum()
-        elif tagname == "SASprocess":
-            data1d = Process()
-            for child in children:
-                if child.tag.replace(self.base_ns, "") == "term":
-                    term_attr = {}
-                    for attr in child.keys():
-                        term_attr[attr] = \
-                            ' '.join(child.get(attr).split())
-                    if child.text is not None:
-                        term_attr['value'] = \
-                            ' '.join(child.text.split())
-                    data1d.term.append(term_attr)
-        elif tagname == "aperture":
-            data1d = Aperture()
-        if tagname == "Idata" and children is not None:
-            data1d = self._check_for_empty_resolution(data1d, children)
-        return data1d
-
-    def _check_for_empty_resolution(self, data1d, children):
+        if self.current_dataset == None:
+            x_vals = np.empty(0)
+            y_vals = np.empty(0)
+            dx_vals = np.empty(0)
+            dy_vals = np.empty(0)
+            dxl = np.empty(0)
+            dxw = np.empty(0)
+            self.current_dataset = plottable_1D(x_vals, y_vals, dx_vals, dy_vals)
+            self.current_dataset.dxl = dxl
+            self.current_dataset.dxw = dxw
+
+    def _check_for_empty_resolution(self):
         """
         A method to check all resolution data sets are the same size as I and Q
@@ -408,623 +694,45 @@
         dq_exists = False
         di_exists = False
-        for child in children:
-            tag = child.tag.replace(self.base_ns, "")
-            if tag == "dQl":
-                dql_exists = True
-            if tag == "dQw":
-                dqw_exists = True
-            if tag == "Qdev":
-                dq_exists = True
-            if tag == "Idev":
-                di_exists = True
-        if dqw_exists and dql_exists == False:
-            data1d.dxl = numpy.append(data1d.dxl, 0.0)
-        elif dql_exists and dqw_exists == False:
-            data1d.dxw = numpy.append(data1d.dxw, 0.0)
-        elif dql_exists == False and dqw_exists == False \
-                                            and dq_exists == False:
-            data1d.dx = numpy.append(data1d.dx, 0.0)
-        if di_exists == False:
-            data1d.dy = numpy.append(data1d.dy, 0.0)
-        return data1d
-
-    def _restore_original_case(self,
-                               tagname_original,
-                               tagname,
-                               save_data1d,
-                               data1d):
-        """
-        Save the special case data to the appropriate location and restore
-        the original Data1D object
-
-        :param tagname_original: Unmodified tagname for the node
-        :param tagname: modified tagname for the node
-        :param save_data1d: The original Data1D object
-        :param data1d: If a special case was handled, an object of that type
-        """
-        if tagname_original == "SASdetector":
-            save_data1d.detector.append(data1d)
-        elif tagname_original == "SAScollimation":
-            save_data1d.collimation.append(data1d)
-        elif tagname == "SAStransmission_spectrum":
-            save_data1d.trans_spectrum.append(data1d)
-        elif tagname_original == "SASprocess":
-            save_data1d.process.append(data1d)
-        elif tagname_original == "aperture":
-            save_data1d.aperture.append(data1d)
-        else:
-            save_data1d = data1d
-        return save_data1d
-
-    def _handle_attributes(self, node, data1d, cs_values, tagname):
-        """
-        Process all of the attributes for a node
-        """
-        attr = node.attrib
-        if attr is not None:
-            for key in node.keys():
-                try:
-                    node_value, unit = self._get_node_value(node, cs_values, \
-                                                   data1d, tagname)
-                    cansas_attrib = \
-                        cs_values.current_level.get("attributes").get(key)
-                    attrib_variable = cansas_attrib.get("variable")
-                    if key == 'unit' and unit != '':
-                        attrib_value = unit
-                    else:
-                        attrib_value = node.attrib[key]
-                    store_attr = attrib_variable.format("data1d",
-                                                        attrib_value,
-                                                        key,
-                                                        node_value)
-                    exec store_attr
-                except AttributeError:
-                    pass
-        return data1d
-
-    def _get_node_value(self, node, cs_values, data1d, tagname):
-        """
-        Get the value of a node and any applicable units
-
-        :param node: The XML node to get the value of
-        :param cs_values: A CansasConstants.CurrentLevel object
-        :param attr: The node attributes
-        :param dataid: The working object to be modified
-        :param tagname: The tagname of the node
-        """
-        #Get the text from the node and convert all whitespace to spaces
-        units = ''
-        node_value = node.text
-        if node_value == "":
-            node_value = None
-        if node_value is not None:
-            node_value = ' '.join(node_value.split())
-
-        # If the value is a float, compile with units.
-        if cs_values.ns_datatype == "float":
-            # If an empty value is given, set as zero.
-            if node_value is None or node_value.isspace() \
-                                    or node_value.lower() == "nan":
-                node_value = "0.0"
-            #Convert the value to the base units
-            node_value, units = self._unit_conversion(node, \
-                        cs_values.current_level, data1d, tagname, node_value)
-
-        # If the value is a timestamp, convert to a datetime object
-        elif cs_values.ns_datatype == "timestamp":
-            if node_value is None or node_value.isspace():
-                pass
-            else:
-                try:
-                    node_value = \
-                        datetime.datetime.fromtimestamp(node_value)
-                except ValueError:
-                    node_value = None
-        return node_value, units
-
-    def _parse_entry(self, dom, names=None, data1d=None, extras=None):
-        """
-        Parse a SASEntry - new recursive method for parsing the dom of
-            the CanSAS data format. This will allow multiple data files
-            and extra nodes to be read in simultaneously.
-
-        :param dom: dom object with a namespace base of names
-        :param names: A list of element names that lead up to the dom object
-        :param data1d: The data1d object that will be modified
-        :param extras: Any values that should go into meta_data when data1d
-            is not a Data1D object
-        """
-
-        if extras is None:
-            extras = []
-        if names is None or names == []:
-            names = ["SASentry"]
-
-        data1d = self._check_for_empty_data(data1d)
-
-        self.base_ns = "{0}{1}{2}".format("{", \
-                            CANSAS_NS.get(self.cansas_version).get("ns"), "}")
-        tagname = ''
-        tagname_original = ''
-
-        # Go through each child in the parent element
-        for node in dom:
-            try:
-                # Get the element name and set the current names level
-                tagname = node.tag.replace(self.base_ns, "")
-                tagname_original = tagname
-                if tagname == "fitting_plug_in" or tagname == "pr_inversion" or\
-                    tagname == "invariant":
-                    continue
-                names.append(tagname)
-                children = node.getchildren()
-                if len(children) == 0:
-                    children = None
-                save_data1d = data1d
-
-                # Look for special cases
-                data1d = self._handle_special_cases(tagname, data1d, children)
-
-                # Get where to store content
-                cs_values = CONSTANTS.iterate_namespace(names)
-                # If the element is a child element, recurse
-                if children is not None:
-                    # Returned value is new Data1D object with all previous and
-                    # new values in it.
-                    data1d, extras = self._parse_entry(node,
-                                                       names, data1d, extras)
-
-                #Get the information from the node
-                node_value, _ = self._get_node_value(node, cs_values, \
-                                                            data1d, tagname)
-
-                # If appending to a dictionary (meta_data | run_name)
-                # make sure the key is unique
-                if cs_values.ns_variable == "{0}.meta_data[\"{2}\"] = \"{1}\"":
-                    # If we are within a Process, Detector, Collimation or
-                    # Aperture instance, pull out old data1d
-                    tagname = self._create_unique_key(data1d.meta_data, \
-                                                      tagname, 0)
-                    if isinstance(data1d, Data1D) == False:
-                        store_me = cs_values.ns_variable.format("data1d", \
-                                                            node_value, tagname)
-                        extras.append(store_me)
-                        cs_values.ns_variable = None
-                if cs_values.ns_variable == "{0}.run_name[\"{2}\"] = \"{1}\"":
-                    tagname = self._create_unique_key(data1d.run_name, \
-                                                      tagname, 0)
-
-                # Check for Data1D object and any extra commands to save
-                if isinstance(data1d, Data1D):
-                    for item in extras:
-                        exec item
-                # Don't bother saving empty information unless it is a float
-                if cs_values.ns_variable is not None and \
-                            node_value is not None and \
-                            node_value.isspace() == False:
-                    # Format a string and then execute it.
-                    store_me = cs_values.ns_variable.format("data1d", \
-                                                            node_value, tagname)
-                    exec store_me
-                # Get attributes and process them
-                data1d = self._handle_attributes(node, data1d, cs_values, \
-                                                 tagname)
-
-            except TypeError:
-                pass
-            except Exception as excep:
-                exc_type, exc_obj, exc_tb = sys.exc_info()
-                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
-                print(excep, exc_type, fname, exc_tb.tb_lineno, \
-                      tagname, exc_obj)
-            finally:
-                # Save special cases in original data1d object
-                # then restore the data1d
-                save_data1d = self._restore_original_case(tagname_original, \
-                                                tagname, save_data1d, data1d)
-                if tagname_original == "fitting_plug_in" or \
-                    tagname_original == "invariant" or \
-                    tagname_original == "pr_inversion":
-                    pass
-                else:
-                    data1d = save_data1d
-                    # Remove tagname from names to restore original base
-                    names.remove(tagname_original)
-        return data1d, extras
-
-    def _get_pi_string(self):
-        """
-        Creates the processing instructions header for writing to file
-        """
-        pis = self.return_processing_instructions()
-        if len(pis) > 0:
-            pi_tree = self.create_tree(pis[0])
-            i = 1
-            for i in range(1, len(pis) - 1):
-                pi_tree = self.append(pis[i], pi_tree)
-            pi_string = self.to_string(pi_tree)
-        else:
-            pi_string = ""
-        return pi_string
-
-    def _create_main_node(self):
-        """
-        Creates the primary xml header used when writing to file
-        """
-        xsi = "http://www.w3.org/2001/XMLSchema-instance"
-        version = self.cansas_version
-        n_s = CANSAS_NS.get(version).get("ns")
-        if version == "1.1":
-            url = "http://www.cansas.org/formats/1.1/"
-        else:
-            url = "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/"
-        schema_location = "{0} {1}cansas1d.xsd".format(n_s, url)
-        attrib = {"{" + xsi + "}schemaLocation" : schema_location,
-                  "version" : version}
-        nsmap = {'xsi' : xsi, None: n_s}
-
-        main_node = self.create_element("{" + n_s + "}SASroot",
-                                        attrib=attrib, nsmap=nsmap)
-        return main_node
-
-    def _write_run_names(self, datainfo, entry_node):
-        """
-        Writes the run names to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-        """
-        if datainfo.run == None or datainfo.run == []:
-            datainfo.run.append(RUN_NAME_DEFAULT)
-            datainfo.run_name[RUN_NAME_DEFAULT] = RUN_NAME_DEFAULT
-        for item in datainfo.run:
-            runname = {}
-            if item in datainfo.run_name and \
-            len(str(datainfo.run_name[item])) > 1:
-                runname = {'name': datainfo.run_name[item]}
-            self.write_node(entry_node, "Run", item, runname)
-
-    def _write_data(self, datainfo, entry_node):
-        """
-        Writes the I and Q data to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-        """
-        node = self.create_element("SASdata")
-        self.append(node, entry_node)
-
-        for i in range(len(datainfo.x)):
-            point = self.create_element("Idata")
-            node.append(point)
-            self.write_node(point, "Q", datainfo.x[i],
-                            {'unit': datainfo.x_unit})
-            if len(datainfo.y) >= i:
-                self.write_node(point, "I", datainfo.y[i],
-                                {'unit': datainfo.y_unit})
-            if datainfo.dy != None and len(datainfo.dy) > i:
-                self.write_node(point, "Idev", datainfo.dy[i],
-                                {'unit': datainfo.y_unit})
-            if datainfo.dx != None and len(datainfo.dx) > i:
-                self.write_node(point, "Qdev", datainfo.dx[i],
-                                {'unit': datainfo.x_unit})
-            if datainfo.dxw != None and len(datainfo.dxw) > i:
-                self.write_node(point, "dQw", datainfo.dxw[i],
-                                {'unit': datainfo.x_unit})
-            if datainfo.dxl != None and len(datainfo.dxl) > i:
-                self.write_node(point, "dQl", datainfo.dxl[i],
-                                {'unit': datainfo.x_unit})
-
-    def _write_trans_spectrum(self, datainfo, entry_node):
-        """
-        Writes the transmission spectrum data to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-        """
-        for i in range(len(datainfo.trans_spectrum)):
-            spectrum = datainfo.trans_spectrum[i]
-            node = self.create_element("SAStransmission_spectrum",
-                                       {"name" : spectrum.name})
-            self.append(node, entry_node)
-            if isinstance(spectrum.timestamp, datetime.datetime):
-                node.setAttribute("timestamp", spectrum.timestamp)
-            for i in range(len(spectrum.wavelength)):
-                point = self.create_element("Tdata")
-                node.append(point)
-                self.write_node(point, "Lambda", spectrum.wavelength[i],
-                                {'unit': spectrum.wavelength_unit})
-                self.write_node(point, "T", spectrum.transmission[i],
-                                {'unit': spectrum.transmission_unit})
-                if spectrum.transmission_deviation != None \
-                and len(spectrum.transmission_deviation) >= i:
-                    self.write_node(point, "Tdev",
-                                    spectrum.transmission_deviation[i],
-                                    {'unit':
-                                     spectrum.transmission_deviation_unit})
-
-    def _write_sample_info(self, datainfo, entry_node):
-        """
-        Writes the sample information to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-        """
-        sample = self.create_element("SASsample")
-        if datainfo.sample.name is not None:
-            self.write_attribute(sample, "name",
-                                 str(datainfo.sample.name))
-        self.append(sample, entry_node)
-        self.write_node(sample, "ID", str(datainfo.sample.ID))
-        self.write_node(sample, "thickness", datainfo.sample.thickness,
-                        {"unit": datainfo.sample.thickness_unit})
-        self.write_node(sample, "transmission", datainfo.sample.transmission)
-        self.write_node(sample, "temperature", datainfo.sample.temperature,
-                        {"unit": datainfo.sample.temperature_unit})
-
-        pos = self.create_element("position")
-        written = self.write_node(pos,
-                                  "x",
-                                  datainfo.sample.position.x,
-                                  {"unit": datainfo.sample.position_unit})
-        written = written | self.write_node( \
-            pos, "y", datainfo.sample.position.y,
-            {"unit": datainfo.sample.position_unit})
-        written = written | self.write_node( \
-            pos, "z", datainfo.sample.position.z,
-            {"unit": datainfo.sample.position_unit})
-        if written == True:
-            self.append(pos, sample)
-
-        ori = self.create_element("orientation")
-        written = self.write_node(ori, "roll",
-                                  datainfo.sample.orientation.x,
-                                  {"unit": datainfo.sample.orientation_unit})
-        written = written | self.write_node( \
-            ori, "pitch", datainfo.sample.orientation.y,
-            {"unit": datainfo.sample.orientation_unit})
-        written = written | self.write_node( \
-            ori, "yaw", datainfo.sample.orientation.z,
-            {"unit": datainfo.sample.orientation_unit})
-        if written == True:
-            self.append(ori, sample)
-
-        for item in datainfo.sample.details:
-            self.write_node(sample, "details", item)
-
-    def _write_instrument(self, datainfo, entry_node):
-        """
-        Writes the instrumental information to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-        """
-        instr = self.create_element("SASinstrument")
-        self.append(instr, entry_node)
-        self.write_node(instr, "name", datainfo.instrument)
-        return instr
-
-    def _write_source(self, datainfo, instr):
-        """
-        Writes the source information to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param instr: instrument node  to be appended to
-        """
-        source = self.create_element("SASsource")
-        if datainfo.source.name is not None:
-            self.write_attribute(source, "name",
-                                 str(datainfo.source.name))
-        self.append(source, instr)
-        if datainfo.source.radiation == None or datainfo.source.radiation == '':
-            datainfo.source.radiation = "neutron"
-        self.write_node(source, "radiation", datainfo.source.radiation)
-
-        size = self.create_element("beam_size")
-        if datainfo.source.beam_size_name is not None:
-            self.write_attribute(size, "name",
-                                 str(datainfo.source.beam_size_name))
-        written = self.write_node( \
-            size, "x", datainfo.source.beam_size.x,
-            {"unit": datainfo.source.beam_size_unit})
-        written = written | self.write_node( \
-            size, "y", datainfo.source.beam_size.y,
-            {"unit": datainfo.source.beam_size_unit})
-        written = written | self.write_node( \
-            size, "z", datainfo.source.beam_size.z,
-            {"unit": datainfo.source.beam_size_unit})
-        if written == True:
-            self.append(size, source)
-
-        self.write_node(source, "beam_shape", datainfo.source.beam_shape)
-        self.write_node(source, "wavelength",
-                        datainfo.source.wavelength,
-                        {"unit": datainfo.source.wavelength_unit})
-        self.write_node(source, "wavelength_min",
-                        datainfo.source.wavelength_min,
-                        {"unit": datainfo.source.wavelength_min_unit})
-        self.write_node(source, "wavelength_max",
-                        datainfo.source.wavelength_max,
-                        {"unit": datainfo.source.wavelength_max_unit})
-        self.write_node(source, "wavelength_spread",
-                        datainfo.source.wavelength_spread,
-                        {"unit": datainfo.source.wavelength_spread_unit})
-
-    def _write_collimation(self, datainfo, instr):
-        """
-        Writes the collimation information to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param instr: lxml node ElementTree object to be appended to
-        """
-        if datainfo.collimation == [] or datainfo.collimation == None:
-            coll = Collimation()
-            datainfo.collimation.append(coll)
-        for item in datainfo.collimation:
-            coll = self.create_element("SAScollimation")
-            if item.name is not None:
-                self.write_attribute(coll, "name", str(item.name))
-            self.append(coll, instr)
-
-            self.write_node(coll, "length", item.length,
-                            {"unit": item.length_unit})
-
-            for aperture in item.aperture:
-                apert = self.create_element("aperture")
-                if aperture.name is not None:
-                    self.write_attribute(apert, "name", str(aperture.name))
-                if aperture.type is not None:
-                    self.write_attribute(apert, "type", str(aperture.type))
-                self.append(apert, coll)
-
-                size = self.create_element("size")
-                if aperture.size_name is not None:
-                    self.write_attribute(size, "name",
-                                         str(aperture.size_name))
-                written = self.write_node(size, "x", aperture.size.x,
-                                          {"unit": aperture.size_unit})
-                written = written | self.write_node( \
-                    size, "y", aperture.size.y,
-                    {"unit": aperture.size_unit})
-                written = written | self.write_node( \
-                    size, "z", aperture.size.z,
-                    {"unit": aperture.size_unit})
-                if written == True:
-                    self.append(size, apert)
-
-                self.write_node(apert, "distance", aperture.distance,
-                                {"unit": aperture.distance_unit})
-
-    def _write_detectors(self, datainfo, instr):
-        """
-        Writes the detector information to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param inst: lxml instrument node to be appended to
-        """
-        if datainfo.detector == None or datainfo.detector == []:
-            det = Detector()
-            det.name = ""
-            datainfo.detector.append(det)
-
-        for item in datainfo.detector:
-            det = self.create_element("SASdetector")
-            written = self.write_node(det, "name", item.name)
-            written = written | self.write_node(det, "SDD", item.distance,
-                                                {"unit": item.distance_unit})
-            if written == True:
-                self.append(det, instr)
-
-            off = self.create_element("offset")
-            written = self.write_node(off, "x", item.offset.x,
-                                      {"unit": item.offset_unit})
-            written = written | self.write_node(off, "y", item.offset.y,
-                                                {"unit": item.offset_unit})
-            written = written | self.write_node(off, "z", item.offset.z,
-                                                {"unit": item.offset_unit})
-            if written == True:
-                self.append(off, det)
-
-            ori = self.create_element("orientation")
-            written = self.write_node(ori, "roll", item.orientation.x,
-                                      {"unit": item.orientation_unit})
-            written = written | self.write_node(ori, "pitch",
-                                                item.orientation.y,
-                                                {"unit": item.orientation_unit})
-            written = written | self.write_node(ori, "yaw",
-                                                item.orientation.z,
-                                                {"unit": item.orientation_unit})
-            if written == True:
-                self.append(ori, det)
-
-            center = self.create_element("beam_center")
-            written = self.write_node(center, "x", item.beam_center.x,
-                                      {"unit": item.beam_center_unit})
-            written = written | self.write_node(center, "y",
-                                                item.beam_center.y,
-                                                {"unit": item.beam_center_unit})
-            written = written | self.write_node(center, "z",
-                                                item.beam_center.z,
-                                                {"unit": item.beam_center_unit})
-            if written == True:
-                self.append(center, det)
-
-            pix = self.create_element("pixel_size")
-            written = self.write_node(pix, "x", item.pixel_size.x,
-                                      {"unit": item.pixel_size_unit})
-            written = written | self.write_node(pix, "y", item.pixel_size.y,
-                                                {"unit": item.pixel_size_unit})
-            written = written | self.write_node(pix, "z", item.pixel_size.z,
-                                                {"unit": item.pixel_size_unit})
-            written = written | self.write_node(det, "slit_length",
-                                                item.slit_length,
-                                                {"unit": item.slit_length_unit})
-            if written == True:
-                self.append(pix, det)
-
-    def _write_process_notes(self, datainfo, entry_node):
-        """
-        Writes the process notes to the XML file
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-
-        """
-        for item in datainfo.process:
-            node = self.create_element("SASprocess")
-            self.append(node, entry_node)
-            self.write_node(node, "name", item.name)
-            self.write_node(node, "date", item.date)
-            self.write_node(node, "description", item.description)
-            for term in item.term:
-                value = term['value']
-                del term['value']
-                self.write_node(node, "term", value, term)
-            for note in item.notes:
-                self.write_node(node, "SASprocessnote", note)
-            if len(item.notes) == 0:
-                self.write_node(node, "SASprocessnote", "")
-
-    def _write_notes(self, datainfo, entry_node):
-        """
-        Writes the notes to the XML file and creates an empty note if none
-        exist
-
-        :param datainfo: The Data1D object the information is coming from
-        :param entry_node: lxml node ElementTree object to be appended to
-
-        """
-        if len(datainfo.notes) == 0:
-            node = self.create_element("SASnote")
-            self.append(node, entry_node)
-        else:
-            for item in datainfo.notes:
-                node = self.create_element("SASnote")
-                self.write_text(node, item)
-                self.append(node, entry_node)
-
-    def _check_origin(self, entry_node, doc, frm):
-        """
-        Return the document, and the SASentry node associated with
-        the data we just wrote.
-        If the calling function was not the cansas reader, return a minidom
-        object rather than an lxml object.
-
-        :param entry_node: lxml node ElementTree object to be appended to
-        :param doc: entire xml tree
-        """
-        if not frm:
-            frm = inspect.stack()[1]
-        mod_name = frm[1].replace("\\", "/").replace(".pyc", "")
-        mod_name = mod_name.replace(".py", "")
-        mod = mod_name.split("sas/")
-        mod_name = mod[1]
-        if mod_name != "sascalc/dataloader/readers/cansas_reader":
-            string = self.to_string(doc, pretty_print=False)
-            doc = parseString(string)
-            node_name = entry_node.tag
-            node_list = doc.getElementsByTagName(node_name)
-            entry_node = node_list.item(0)
-        return doc, entry_node
+        if self.current_dataset.dxl is not None:
+            dql_exists = True
+        if self.current_dataset.dxw is not None:
+            dqw_exists = True
+        if self.current_dataset.dx is not None:
+            dq_exists = True
+        if self.current_dataset.dy is not None:
+            di_exists = True
+        if dqw_exists and not dql_exists:
+            array_size = self.current_dataset.dxw.size - 1
+            self.current_dataset.dxl = np.append(self.current_dataset.dxl, np.zeros([array_size]))
+        elif dql_exists and not dqw_exists:
+            array_size = self.current_dataset.dxl.size - 1
+            self.current_dataset.dxw = np.append(self.current_dataset.dxw, np.zeros([array_size]))
+        elif not dql_exists and not dqw_exists and not dq_exists:
+            array_size = self.current_dataset.x.size - 1
+            self.current_dataset.dx = np.append(self.current_dataset.dx, np.zeros([array_size]))
+        if not di_exists:
+            array_size = self.current_dataset.y.size - 1
+            self.current_dataset.dy = np.append(self.current_dataset.dy, np.zeros([array_size]))
+
+
+    ####### All methods below are for writing CanSAS XML files #######
+
+
+    def write(self, filename, datainfo):
+        """
+        Write the content of a Data1D as a CanSAS XML file
+
+        :param filename: name of the file to write
+        :param datainfo: Data1D object
+        """
+        # Create XML document
+        doc, _ = self._to_xml_doc(datainfo)
+        # Write the file
+        file_ref = open(filename, 'w')
+        if self.encoding == None:
+            self.encoding = "UTF-8"
+        doc.write(file_ref, encoding=self.encoding,
+                  pretty_print=True, xml_declaration=True)
+        file_ref.close()
 
     def _to_xml_doc(self, datainfo):
@@ -1095,20 +803,398 @@
         return False
 
-    def write(self, filename, datainfo):
-        """
-        Write the content of a Data1D as a CanSAS XML file
-
-        :param filename: name of the file to write
-        :param datainfo: Data1D object
-        """
-        # Create XML document
-        doc, _ = self._to_xml_doc(datainfo)
-        # Write the file
-        file_ref = open(filename, 'w')
-        if self.encoding == None:
-            self.encoding = "UTF-8"
-        doc.write(file_ref, encoding=self.encoding,
-                  pretty_print=True, xml_declaration=True)
-        file_ref.close()
+    def _get_pi_string(self):
+        """
+        Creates the processing instructions header for writing to file
+        """
+        pis = self.return_processing_instructions()
+        if len(pis) > 0:
+            pi_tree = self.create_tree(pis[0])
+            i = 1
+            for i in range(1, len(pis) - 1):
+                pi_tree = self.append(pis[i], pi_tree)
+            pi_string = self.to_string(pi_tree)
+        else:
+            pi_string = ""
+        return pi_string
+
+    def _create_main_node(self):
+        """
+        Creates the primary xml header used when writing to file
+        """
+        xsi = "http://www.w3.org/2001/XMLSchema-instance"
+        version = self.cansas_version
+        n_s = CANSAS_NS.get(version).get("ns")
+        if version == "1.1":
+            url = "http://www.cansas.org/formats/1.1/"
+        else:
+            url = "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/"
+        schema_location = "{0} {1}cansas1d.xsd".format(n_s, url)
+        attrib = {"{" + xsi + "}schemaLocation" : schema_location,
+                  "version" : version}
+        nsmap = {'xsi' : xsi, None: n_s}
+
+        main_node = self.create_element("{" + n_s + "}SASroot",
+                                        attrib=attrib, nsmap=nsmap)
+        return main_node
+
+    def _write_run_names(self, datainfo, entry_node):
+        """
+        Writes the run names to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+        """
+        if datainfo.run == None or datainfo.run == []:
+            datainfo.run.append(RUN_NAME_DEFAULT)
+            datainfo.run_name[RUN_NAME_DEFAULT] = RUN_NAME_DEFAULT
+        for item in datainfo.run:
+            runname = {}
+            if item in datainfo.run_name and \
+            len(str(datainfo.run_name[item])) > 1:
+                runname = {'name': datainfo.run_name[item]}
+            self.write_node(entry_node, "Run", item, runname)
+
+    def _write_data(self, datainfo, entry_node):
+        """
+        Writes the I and Q data to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+        """
+        node = self.create_element("SASdata")
+        self.append(node, entry_node)
+
+        for i in range(len(datainfo.x)):
+            point = self.create_element("Idata")
+            node.append(point)
+            self.write_node(point, "Q", datainfo.x[i],
+                            {'unit': datainfo.x_unit})
+            if len(datainfo.y) >= i:
+                self.write_node(point, "I", datainfo.y[i],
+                                {'unit': datainfo.y_unit})
+            if datainfo.dy != None and len(datainfo.dy) > i:
+                self.write_node(point, "Idev", datainfo.dy[i],
+                                {'unit': datainfo.y_unit})
+            if datainfo.dx != None and len(datainfo.dx) > i:
+                self.write_node(point, "Qdev", datainfo.dx[i],
+                                {'unit': datainfo.x_unit})
+            if datainfo.dxw != None and len(datainfo.dxw) > i:
+                self.write_node(point, "dQw", datainfo.dxw[i],
+                                {'unit': datainfo.x_unit})
+            if datainfo.dxl != None and len(datainfo.dxl) > i:
+                self.write_node(point, "dQl", datainfo.dxl[i],
+                                {'unit': datainfo.x_unit})
+
+    def _write_trans_spectrum(self, datainfo, entry_node):
+        """
+        Writes the transmission spectrum data to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+        """
+        for i in range(len(datainfo.trans_spectrum)):
+            spectrum = datainfo.trans_spectrum[i]
+            node = self.create_element("SAStransmission_spectrum",
+                                       {"name" : spectrum.name})
+            self.append(node, entry_node)
+            if isinstance(spectrum.timestamp, datetime.datetime):
+                node.setAttribute("timestamp", spectrum.timestamp)
+            for i in range(len(spectrum.wavelength)):
+                point = self.create_element("Tdata")
+                node.append(point)
+                self.write_node(point, "Lambda", spectrum.wavelength[i],
+                                {'unit': spectrum.wavelength_unit})
+                self.write_node(point, "T", spectrum.transmission[i],
+                                {'unit': spectrum.transmission_unit})
+                if spectrum.transmission_deviation != None \
+                and len(spectrum.transmission_deviation) >= i:
+                    self.write_node(point, "Tdev",
+                                    spectrum.transmission_deviation[i],
+                                    {'unit':
+                                     spectrum.transmission_deviation_unit})
+
+    def _write_sample_info(self, datainfo, entry_node):
+        """
+        Writes the sample information to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+        """
+        sample = self.create_element("SASsample")
+        if datainfo.sample.name is not None:
+            self.write_attribute(sample, "name",
+                                 str(datainfo.sample.name))
+        self.append(sample, entry_node)
+        self.write_node(sample, "ID", str(datainfo.sample.ID))
+        self.write_node(sample, "thickness", datainfo.sample.thickness,
+                        {"unit": datainfo.sample.thickness_unit})
+        self.write_node(sample, "transmission", datainfo.sample.transmission)
+        self.write_node(sample, "temperature", datainfo.sample.temperature,
+                        {"unit": datainfo.sample.temperature_unit})
+
+        pos = self.create_element("position")
+        written = self.write_node(pos,
+                                  "x",
+                                  datainfo.sample.position.x,
+                                  {"unit": datainfo.sample.position_unit})
+        written = written | self.write_node( \
+            pos, "y", datainfo.sample.position.y,
+            {"unit": datainfo.sample.position_unit})
+        written = written | self.write_node( \
+            pos, "z", datainfo.sample.position.z,
+            {"unit": datainfo.sample.position_unit})
+        if written == True:
+            self.append(pos, sample)
+
+        ori = self.create_element("orientation")
+        written = self.write_node(ori, "roll",
+                                  datainfo.sample.orientation.x,
+                                  {"unit": datainfo.sample.orientation_unit})
+        written = written | self.write_node( \
+            ori, "pitch", datainfo.sample.orientation.y,
+            {"unit": datainfo.sample.orientation_unit})
+        written = written | self.write_node( \
+            ori, "yaw", datainfo.sample.orientation.z,
+            {"unit": datainfo.sample.orientation_unit})
+        if written == True:
+            self.append(ori, sample)
+
+        for item in datainfo.sample.details:
+            self.write_node(sample, "details", item)
+
+    def _write_instrument(self, datainfo, entry_node):
+        """
+        Writes the instrumental information to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+        """
+        instr = self.create_element("SASinstrument")
+        self.append(instr, entry_node)
+        self.write_node(instr, "name", datainfo.instrument)
+        return instr
+
+    def _write_source(self, datainfo, instr):
+        """
+        Writes the source information to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param instr: instrument node  to be appended to
+        """
+        source = self.create_element("SASsource")
+        if datainfo.source.name is not None:
+            self.write_attribute(source, "name",
+                                 str(datainfo.source.name))
+        self.append(source, instr)
+        if datainfo.source.radiation == None or datainfo.source.radiation == '':
+            datainfo.source.radiation = "neutron"
+        self.write_node(source, "radiation", datainfo.source.radiation)
+
+        size = self.create_element("beam_size")
+        if datainfo.source.beam_size_name is not None:
+            self.write_attribute(size, "name",
+                                 str(datainfo.source.beam_size_name))
+        written = self.write_node( \
+            size, "x", datainfo.source.beam_size.x,
+            {"unit": datainfo.source.beam_size_unit})
+        written = written | self.write_node( \
+            size, "y", datainfo.source.beam_size.y,
+            {"unit": datainfo.source.beam_size_unit})
+        written = written | self.write_node( \
+            size, "z", datainfo.source.beam_size.z,
+            {"unit": datainfo.source.beam_size_unit})
+        if written == True:
+            self.append(size, source)
+
+        self.write_node(source, "beam_shape", datainfo.source.beam_shape)
+        self.write_node(source, "wavelength",
+                        datainfo.source.wavelength,
+                        {"unit": datainfo.source.wavelength_unit})
+        self.write_node(source, "wavelength_min",
+                        datainfo.source.wavelength_min,
+                        {"unit": datainfo.source.wavelength_min_unit})
+        self.write_node(source, "wavelength_max",
+                        datainfo.source.wavelength_max,
+                        {"unit": datainfo.source.wavelength_max_unit})
+        self.write_node(source, "wavelength_spread",
+                        datainfo.source.wavelength_spread,
+                        {"unit": datainfo.source.wavelength_spread_unit})
+
+    def _write_collimation(self, datainfo, instr):
+        """
+        Writes the collimation information to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param instr: lxml node ElementTree object to be appended to
+        """
+        if datainfo.collimation == [] or datainfo.collimation == None:
+            coll = Collimation()
+            datainfo.collimation.append(coll)
+        for item in datainfo.collimation:
+            coll = self.create_element("SAScollimation")
+            if item.name is not None:
+                self.write_attribute(coll, "name", str(item.name))
+            self.append(coll, instr)
+
+            self.write_node(coll, "length", item.length,
+                            {"unit": item.length_unit})
+
+            for aperture in item.aperture:
+                apert = self.create_element("aperture")
+                if aperture.name is not None:
+                    self.write_attribute(apert, "name", str(aperture.name))
+                if aperture.type is not None:
+                    self.write_attribute(apert, "type", str(aperture.type))
+                self.append(apert, coll)
+
+                size = self.create_element("size")
+                if aperture.size_name is not None:
+                    self.write_attribute(size, "name",
+                                         str(aperture.size_name))
+                written = self.write_node(size, "x", aperture.size.x,
+                                          {"unit": aperture.size_unit})
+                written = written | self.write_node( \
+                    size, "y", aperture.size.y,
+                    {"unit": aperture.size_unit})
+                written = written | self.write_node( \
+                    size, "z", aperture.size.z,
+                    {"unit": aperture.size_unit})
+                if written == True:
+                    self.append(size, apert)
+
+                self.write_node(apert, "distance", aperture.distance,
+                                {"unit": aperture.distance_unit})
+
+    def _write_detectors(self, datainfo, instr):
+        """
+        Writes the detector information to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param inst: lxml instrument node to be appended to
+        """
+        if datainfo.detector == None or datainfo.detector == []:
+            det = Detector()
+            det.name = ""
+            datainfo.detector.append(det)
+
+        for item in datainfo.detector:
+            det = self.create_element("SASdetector")
+            written = self.write_node(det, "name", item.name)
+            written = written | self.write_node(det, "SDD", item.distance,
+                                                {"unit": item.distance_unit})
+            if written == True:
+                self.append(det, instr)
+
+            off = self.create_element("offset")
+            written = self.write_node(off, "x", item.offset.x,
+                                      {"unit": item.offset_unit})
+            written = written | self.write_node(off, "y", item.offset.y,
+                                                {"unit": item.offset_unit})
+            written = written | self.write_node(off, "z", item.offset.z,
+                                                {"unit": item.offset_unit})
+            if written == True:
+                self.append(off, det)
+
+            ori = self.create_element("orientation")
+            written = self.write_node(ori, "roll", item.orientation.x,
+                                      {"unit": item.orientation_unit})
+            written = written | self.write_node(ori, "pitch",
+                                                item.orientation.y,
+                                                {"unit": item.orientation_unit})
+            written = written | self.write_node(ori, "yaw",
+                                                item.orientation.z,
+                                                {"unit": item.orientation_unit})
+            if written == True:
+                self.append(ori, det)
+
+            center = self.create_element("beam_center")
+            written = self.write_node(center, "x", item.beam_center.x,
+                                      {"unit": item.beam_center_unit})
+            written = written | self.write_node(center, "y",
+                                                item.beam_center.y,
+                                                {"unit": item.beam_center_unit})
+            written = written | self.write_node(center, "z",
+                                                item.beam_center.z,
+                                                {"unit": item.beam_center_unit})
+            if written == True:
+                self.append(center, det)
+
+            pix = self.create_element("pixel_size")
+            written = self.write_node(pix, "x", item.pixel_size.x,
+                                      {"unit": item.pixel_size_unit})
+            written = written | self.write_node(pix, "y", item.pixel_size.y,
+                                                {"unit": item.pixel_size_unit})
+            written = written | self.write_node(pix, "z", item.pixel_size.z,
+                                                {"unit": item.pixel_size_unit})
+            written = written | self.write_node(det, "slit_length",
+                                                item.slit_length,
+                                                {"unit": item.slit_length_unit})
+            if written == True:
+                self.append(pix, det)
+
+    def _write_process_notes(self, datainfo, entry_node):
+        """
+        Writes the process notes to the XML file
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+
+        """
+        for item in datainfo.process:
+            node = self.create_element("SASprocess")
+            self.append(node, entry_node)
+            self.write_node(node, "name", item.name)
+            self.write_node(node, "date", item.date)
+            self.write_node(node, "description", item.description)
+            for term in item.term:
+                value = term['value']
+                del term['value']
+                self.write_node(node, "term", value, term)
+            for note in item.notes:
+                self.write_node(node, "SASprocessnote", note)
+            if len(item.notes) == 0:
+                self.write_node(node, "SASprocessnote", "")
+
+    def _write_notes(self, datainfo, entry_node):
+        """
+        Writes the notes to the XML file and creates an empty note if none
+        exist
+
+        :param datainfo: The Data1D object the information is coming from
+        :param entry_node: lxml node ElementTree object to be appended to
+
+        """
+        if len(datainfo.notes) == 0:
+            node = self.create_element("SASnote")
+            self.append(node, entry_node)
+        else:
+            for item in datainfo.notes:
+                node = self.create_element("SASnote")
+                self.write_text(node, item)
+                self.append(node, entry_node)
+
+    def _check_origin(self, entry_node, doc, frm):
+        """
+        Return the document, and the SASentry node associated with
+        the data we just wrote.
+        If the calling function was not the cansas reader, return a minidom
+        object rather than an lxml object.
+
+        :param entry_node: lxml node ElementTree object to be appended to
+        :param doc: entire xml tree
+        """
+        if not frm:
+            frm = inspect.stack()[1]
+        mod_name = frm[1].replace("\\", "/").replace(".pyc", "")
+        mod_name = mod_name.replace(".py", "")
+        mod = mod_name.split("sas/")
+        mod_name = mod[1]
+        if mod_name != "sascalc/dataloader/readers/cansas_reader":
+            string = self.to_string(doc, pretty_print=False)
+            doc = parseString(string)
+            node_name = entry_node.tag
+            node_list = doc.getElementsByTagName(node_name)
+            entry_node = node_list.item(0)
+        return doc, entry_node
 
     # DO NOT REMOVE - used in saving and loading panel states.
@@ -1195,2 +1281,45 @@
         if entry is not None and entry.text is not None:
             exec "storage.%s = entry.text.strip()" % variable
+
+
+# DO NOT REMOVE Called by outside packages:
+#    sas.sasgui.perspectives.invariant.invariant_state
+#    sas.sasgui.perspectives.fitting.pagestate
+def get_content(location, node):
+    """
+    Get the first instance of the content of a xpath location.
+
+    :param location: xpath location
+    :param node: node to start at
+
+    :return: Element, or None
+    """
+    nodes = node.xpath(location,
+                       namespaces={'ns': CANSAS_NS.get("1.0").get("ns")})
+    if len(nodes) > 0:
+        return nodes[0]
+    else:
+        return None
+
+# DO NOT REMOVE Called by outside packages:
+#    sas.sasgui.perspectives.fitting.pagestate
+def write_node(doc, parent, name, value, attr=None):
+    """
+    :param doc: document DOM
+    :param parent: parent node
+    :param name: tag of the element
+    :param value: value of the child text node
+    :param attr: attribute dictionary
+
+    :return: True if something was appended, otherwise False
+    """
+    if attr is None:
+        attr = {}
+    if value is not None:
+        node = doc.createElement(name)
+        node.appendChild(doc.createTextNode(str(value)))
+        for item in attr:
+            node.setAttribute(item, attr[item])
+        parent.appendChild(node)
+        return True
+    return False
Index: src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid.xsd
===================================================================
--- src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid.xsd	(revision 83b6408fbfaefa4819b955c697fef834d8f033f6)
+++ 	(revision )
@@ -1,269 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="xsd-documentation.xsl" ?>
-<schema xmlns="http://www.w3.org/2001/XMLSchema"
-	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"  jaxb:version="2.0"
-	targetNamespace="urn:cansas1d:1.1" xmlns:tns="urn:cansas1d:1.1"
-	elementFormDefault="qualified">
-
-<!-- 
-Copyright (c) 2013, UChicago Argonne, LLC
-This file is distributed subject to a Software License Agreement found
-in the file LICENSE that is included with this distribution. 
- -->
- 
-<!-- JAXB: http://java.sun.com/developer/technicalArticles/WebServices/jaxb/ -->
-
-	<complexType name="floatUnitType">
-		<simpleContent>
-			<extension base="float">
-				<attribute name="unit" type="string" use="required" />
-			</extension>
-		</simpleContent>
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<group name="positionGroup">
-		<sequence>
-			<element name="x" type="tns:floatUnitType" minOccurs="0" maxOccurs="1" />
-			<element name="y" type="tns:floatUnitType" minOccurs="0" maxOccurs="1" />
-			<element name="z" type="tns:floatUnitType" minOccurs="0" maxOccurs="1" />
-		</sequence>
-	</group>
-
-	<complexType name="positionType">
-		<group ref="tns:positionGroup" />
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<group name="orientationGroup">
-		<sequence>
-			<element name="roll" type="tns:floatUnitType" minOccurs="0"  maxOccurs="1" />
-			<element name="pitch" type="tns:floatUnitType" minOccurs="0" maxOccurs="1" />
-			<element name="yaw" type="tns:floatUnitType" minOccurs="0"   maxOccurs="1" />
-		</sequence>
-	</group>
-
-	<complexType name="orientationType">
-		<group ref="tns:orientationGroup" />
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-	
-	<complexType name="IdataType">
-		<sequence>
-			<element name="Q" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
-			<element name="I" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
-			<element name="Idev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-			<xsd:choice>
-				<!-- [ [Qdev] | [[dQw] | [dQl]] ] -->
-				<element name="Qdev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-				<xsd:sequence>
-					<element name="dQw" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-					<element name="dQl" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-				</xsd:sequence>
-			</xsd:choice>
-			<element name="Qmean" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-			<element name="Shadowfactor" minOccurs="0" maxOccurs="1" type="float" default="1.0" />
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-	</complexType>
-	
-	<complexType name="SASdataType">
-		<sequence minOccurs="1" maxOccurs="1">  <!-- http://svn.cansas.org/trac/ticket/21 -->
-			<sequence>
-				<element name="Idata" minOccurs="1" maxOccurs="unbounded" type="tns:IdataType" />
-			</sequence>
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-		<attribute name="timestamp" type="dateTime" use="optional" />
-	</complexType>
-	
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-	
-	<complexType name="TdataType">
-			<sequence>
-				<element name="Lambda" minOccurs="0" maxOccurs="1"    type="tns:floatUnitType" />
-				<element name="T" minOccurs="0" maxOccurs="1"    type="tns:floatUnitType" />
-				<element name="Tdev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
-				<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-	</complexType>
-	
-	<complexType name="SAStransmission_spectrumType">
-		<sequence minOccurs="0" maxOccurs="1">
-			<sequence minOccurs="0" maxOccurs="1">
-				<element name="Tdata" minOccurs="0" maxOccurs="unbounded" type="tns:TdataType" />
-			</sequence>
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-		<attribute name="timestamp" type="dateTime" use="optional" />
-	</complexType>
-	
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="SASsampleType">
-		<sequence>
-			<element name="ID" minOccurs="0" maxOccurs="1" type="string" />
-			<element name="thickness" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="transmission" minOccurs="0" maxOccurs="1" type="float" />
-			<element name="temperature" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="position" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-			<element name="orientation" minOccurs="0" maxOccurs="1" type="tns:orientationType" />
-			<element name="details" minOccurs="0" maxOccurs="unbounded" />
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="termType">
-		<simpleContent>
-			<extension base="string">
-				<attribute name="name" type="string" use="optional" default="" />
-				<attribute name="unit" type="string" use="optional"/>
-			</extension>
-		</simpleContent>
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="SASprocessType">
-		<annotation>
-			<appinfo>
-				<!-- JAXB: simplify class name -->
-				<jaxb:property name="SASprocess" />
-			</appinfo>
-		</annotation>
-		<sequence>
-			<element name="name" minOccurs="0" maxOccurs="1" type="string" default="">
-				<annotation>
-					<appinfo>
-						<!-- Remap collision of Name when using JAXB -->
-						<jaxb:property name="SASprocessName" />
-					</appinfo>
-				</annotation>
-			</element>
-			<element name="date" minOccurs="0" maxOccurs="1" type="string" />
-			<element name="description" minOccurs="0" maxOccurs="1" />
-			<element name="term" minOccurs="0" maxOccurs="unbounded" type="tns:termType" />
-			<element name="SASprocessnote" minOccurs="0" maxOccurs="unbounded" />
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="">
-			<annotation>
-				<appinfo>
-					<!-- Remap collision of Name when using JAXB -->
-					<jaxb:property name="SASprocessNameAttr" />
-				</appinfo>
-			</annotation>
-		</attribute>
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="SASsourceType">
-		<sequence>
-			<element name="radiation" minOccurs="0" maxOccurs="1" type="string" />
-			<element name="beam_size" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-			<element name="beam_shape" minOccurs="0" maxOccurs="1" type="string" />
-			<element name="wavelength" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="wavelength_min" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="wavelength_max" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="wavelength_spread" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<complexType name="SAScollimationType">
-		<sequence>
-			<element name="length" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="aperture" minOccurs="0" maxOccurs="unbounded">
-				<complexType>
-					<sequence>
-						<element name="size" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-						<element name="distance" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-					</sequence>
-					<attribute name="name" type="string" use="optional" default="" />
-					<attribute name="type" type="string" use="optional" default="" />
-				</complexType>
-			</element>
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<complexType name="SASdetectorType">
-		<sequence>
-			<element name="name" minOccurs="0" maxOccurs="1" type="string" default=""/>
-			<element name="SDD" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-			<element name="offset" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-			<element name="orientation" minOccurs="0" maxOccurs="1" type="tns:orientationType" />
-			<element name="beam_center" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-			<element name="pixel_size" minOccurs="0" maxOccurs="1" type="tns:positionType" />
-			<element name="slit_length" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" />
-		</sequence>
-	</complexType>
-
-	<complexType name="SASinstrumentType">
-		<sequence>
-			<element name="name" type="string" minOccurs="0" maxOccurs="1" default="" />
-			<element name="SASsource" type="tns:SASsourceType" minOccurs="0" maxOccurs="1" />
-			<element name="SAScollimation" type="tns:SAScollimationType" minOccurs="0" maxOccurs="unbounded" />
-			<element name="SASdetector" type="tns:SASdetectorType" minOccurs="0" maxOccurs="unbounded" />
-		</sequence>
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="SASentryType">
-		<sequence>
-			<element name="Title" minOccurs="0" maxOccurs="1" type="string" />
-			<element name="Run" minOccurs="0" maxOccurs="unbounded">
-				<xsd:complexType>
-					<simpleContent>
-						<extension base="string">
-							<attribute name="name" type="string" use="optional" default="" />
-						</extension>
-					</simpleContent>
-				</xsd:complexType>
-			</element>
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
-			<element name="SASdata" minOccurs="1" maxOccurs="unbounded" type="tns:SASdataType" />
-			<element name="SAStransmission_spectrum" minOccurs="0" maxOccurs="unbounded" type="tns:SAStransmission_spectrumType"/>
-			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other">
-				<!-- Is a second *any* element needed here? -->
-				<annotation>
-					<appinfo>
-						<!-- Remap collision of Any when using JAXB --> 
-						<jaxb:property name="SASentryAny2" />
-					</appinfo>
-				</annotation>
-			</xsd:any>
-			<element name="SASsample" type="tns:SASsampleType" />
-			<element name="SASinstrument" type="tns:SASinstrumentType" minOccurs="0" maxOccurs="1" />
-			<element name="SASprocess" type="tns:SASprocessType" minOccurs="0" maxOccurs="unbounded" />
-			<element name="SASnote" minOccurs="0" maxOccurs="unbounded" />
-				<!-- SASnote is a free-form element.
-					Do not define any content for it or it will become restrictive.
-				-->
-		</sequence>
-		<attribute name="name" type="string" use="optional" default="" />
-	</complexType>
-
-	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
-
-	<complexType name="SASrootType">
-		<sequence>
-			<element name="SASentry" minOccurs="1" maxOccurs="unbounded" type="tns:SASentryType" />
-		</sequence>
-		<attribute name="version" type="string" fixed="1.1" use="optional" />
-	</complexType>
-
-	<element name="SASroot" type="tns:SASrootType" />
-
-</schema>
Index: src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_0.xsd
===================================================================
--- src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_0.xsd	(revision 250fec92ea66b0770da33360a90f022e1d674072)
+++ src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_0.xsd	(revision 250fec92ea66b0770da33360a90f022e1d674072)
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="xsd-documentation.xsl" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"  jaxb:version="2.0"
+	targetNamespace="cansas1d/1.0" xmlns:tns="cansas1d/1.0"
+	elementFormDefault="qualified">
+
+<!-- 
+Copyright (c) 2013, UChicago Argonne, LLC
+This file is distributed subject to a Software License Agreement found
+in the file LICENSE that is included with this distribution. 
+ -->
+ 
+<!-- JAXB: http://java.sun.com/developer/technicalArticles/WebServices/jaxb/ -->
+
+	<complexType name="floatUnitType">
+		<simpleContent>
+			<extension base="string">
+				<attribute name="unit" type="string" use="required" />
+			</extension>
+		</simpleContent>
+	</complexType>
+
+	<complexType name="IdataType">
+		<sequence>
+			<element name="Q" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
+			<element name="I" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
+			<element name="Idev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+			<xsd:choice>
+				<!-- [ [Qdev] | [[dQw] | [dQl]] ] -->
+				<element name="Qdev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+				<xsd:sequence>
+					<element name="dQw" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+					<element name="dQl" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+				</xsd:sequence>
+			</xsd:choice>
+			<element name="Qmean" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+			<element name="Shadowfactor" minOccurs="0" maxOccurs="1" type="string" default="1.0" />
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other" />
+		</sequence>
+	</complexType>
+	
+	<complexType name="SASdataType">
+		<sequence minOccurs="1" maxOccurs="1">  <!-- http://svn.cansas.org/trac/ticket/21 -->
+			<sequence>
+				<element name="Idata" minOccurs="1" maxOccurs="unbounded" type="tns:IdataType" />
+			</sequence>
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other" />
+		</sequence>
+		<attribute name="name" type="string" use="optional" default="" />
+		<attribute name="timestamp" type="dateTime" use="optional" />
+	</complexType>
+
+	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+	<complexType name="SASentryType">
+		<sequence>
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+			<element name="SASdata" minOccurs="1" maxOccurs="unbounded" type="tns:SASdataType" />
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax">
+				<!-- Is a second *any* element needed here? -->
+				<annotation>
+					<appinfo>
+						<!-- Remap collision of Any when using JAXB --> 
+						<jaxb:property name="SASentryAny2" />
+					</appinfo>
+				</annotation>
+			</xsd:any>
+		</sequence>
+		<attribute name="name" type="string" use="optional" default="" />
+	</complexType>
+
+	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+	<complexType name="SASrootType">
+		<sequence>
+			<element name="SASentry" minOccurs="1" maxOccurs="unbounded" type="tns:SASentryType" />
+		</sequence>
+		<attribute name="version" type="string" fixed="1.0" use="optional" />
+	</complexType>
+
+	<element name="SASroot" type="tns:SASrootType" />
+
+</schema>
Index: src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_1.xsd
===================================================================
--- src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_1.xsd	(revision 250fec92ea66b0770da33360a90f022e1d674072)
+++ src/sas/sascalc/dataloader/readers/schema/cansas1d_invalid_v1_1.xsd	(revision 250fec92ea66b0770da33360a90f022e1d674072)
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="xsd-documentation.xsl" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"  jaxb:version="2.0"
+	targetNamespace="urn:cansas1d:1.1" xmlns:tns="urn:cansas1d:1.1"
+	elementFormDefault="qualified">
+
+<!-- 
+Copyright (c) 2013, UChicago Argonne, LLC
+This file is distributed subject to a Software License Agreement found
+in the file LICENSE that is included with this distribution. 
+ -->
+ 
+<!-- JAXB: http://java.sun.com/developer/technicalArticles/WebServices/jaxb/ -->
+
+	<complexType name="floatUnitType">
+		<simpleContent>
+			<extension base="string">
+				<attribute name="unit" type="string" use="required" />
+			</extension>
+		</simpleContent>
+	</complexType>
+
+	<complexType name="IdataType">
+		<sequence>
+			<element name="Q" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
+			<element name="I" minOccurs="1" maxOccurs="1"    type="tns:floatUnitType" />
+			<element name="Idev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+			<xsd:choice>
+				<!-- [ [Qdev] | [[dQw] | [dQl]] ] -->
+				<element name="Qdev" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+				<xsd:sequence>
+					<element name="dQw" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+					<element name="dQl" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+				</xsd:sequence>
+			</xsd:choice>
+			<element name="Qmean" minOccurs="0" maxOccurs="1" type="tns:floatUnitType" default="0" />
+			<element name="Shadowfactor" minOccurs="0" maxOccurs="1" type="string" default="1.0" />
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other" />
+		</sequence>
+	</complexType>
+	
+	<complexType name="SASdataType">
+		<sequence minOccurs="1" maxOccurs="1">  <!-- http://svn.cansas.org/trac/ticket/21 -->
+			<sequence>
+				<element name="Idata" minOccurs="1" maxOccurs="unbounded" type="tns:IdataType" />
+			</sequence>
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other" />
+		</sequence>
+		<attribute name="name" type="string" use="optional" default="" />
+		<attribute name="timestamp" type="dateTime" use="optional" />
+	</complexType>
+
+	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+	<complexType name="SASentryType">
+		<sequence>
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+			<element name="SASdata" minOccurs="1" maxOccurs="unbounded" type="tns:SASdataType" />
+			<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax">
+				<!-- Is a second *any* element needed here? -->
+				<annotation>
+					<appinfo>
+						<!-- Remap collision of Any when using JAXB --> 
+						<jaxb:property name="SASentryAny2" />
+					</appinfo>
+				</annotation>
+			</xsd:any>
+		</sequence>
+		<attribute name="name" type="string" use="optional" default="" />
+	</complexType>
+
+	<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+
+	<complexType name="SASrootType">
+		<sequence>
+			<element name="SASentry" minOccurs="1" maxOccurs="unbounded" type="tns:SASentryType" />
+		</sequence>
+		<attribute name="version" type="string" fixed="1.1" use="optional" />
+	</complexType>
+
+	<element name="SASroot" type="tns:SASrootType" />
+
+</schema>
