Changeset 2e3b055 in sasview for src/sans/dataloader/readers


Ignore:
Timestamp:
Apr 16, 2014 11:50:31 AM (11 years ago)
Author:
Jeff Krzywon <jeffery.krzywon@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
b8de7fb
Parents:
d4117ccb
Message:

Transitioned from minidom to lxml for writing xml for neater output. XMLreader now has helper methods used to read and write xml data. Methods were taken from cansasReader to separate generic XML functions from cansas specific ones.

Location:
src/sans/dataloader/readers
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/sans/dataloader/readers/cansas_reader.py

    r9e2bc6c r2e3b055  
    2525from sans.dataloader.data_info import Aperture 
    2626import sans.dataloader.readers.xml_reader as xml_reader 
    27 import xml.dom.minidom 
    2827from sans.dataloader.readers.cansas_constants import cansasConstants 
    2928 
    3029_ZERO = 1e-16 
    3130PREPROCESS = "xmlpreprocess" 
     31ENCODING = "encoding" 
    3232HAS_CONVERTER = True 
    3333try: 
     
    8383 
    8484 
     85# This is called by sans.perspectives.fitting.pagestate.py 
     86# Do not remove 
    8587def write_node(doc, parent, name, value, attr={}): 
    8688    """ 
     
    113115    cansas_version = "1.0" 
    114116    ##Data reader 
     117    # TODO: make the reader extend the XMLreader class? 
    115118    reader = xml_reader.XMLreader() 
    116119    errors = [] 
     
    135138        """ 
    136139        if self.reader.validateXML(): 
    137             xmlns = self.reader.xmlroot.keys() 
     140            name = "{http://www.w3.org/2001/XMLSchema-instance}schemaLocation" 
     141            value = self.reader.xmlroot.get(name) 
    138142            if (CANSAS_NS.get(self.cansas_version).get("ns") == \ 
    139                     self.reader.xmlroot.get(xmlns[1]).rsplit(" ")[0]): 
     143                    value.rsplit(" ")[0]): 
    140144                return True 
    141145        return False 
     
    184188                # Link a schema to the XML file. 
    185189                self.reader.setSchema(schema_path) 
    186              
     190                 
    187191                # Try to load the file, but raise an error if unable to. 
    188192                # Check the file matches the XML schema 
     
    215219                            data1d.meta_data["loader"] = "CanSAS 1D" 
    216220                             
    217                             # Get all preprocessing events 
     221                            # Get all preprocessing events and encoding 
    218222                            self.reader.setProcessingInstructions() 
    219223                            data1d.meta_data[PREPROCESS] = \ 
     
    521525            raise RuntimeError, "The cansas writer expects a Data1D instance" 
    522526         
    523         ns = CANSAS_NS.get(self.cansas_version).get("ns") 
    524         doc = xml.dom.minidom.Document() 
    525          
    526         main_node = doc.createElement("SASroot") 
    527          
    528         doc = self.setProcessingInstructions(doc, \ 
    529                                         datainfo.meta_data.get(PREPROCESS, {})) 
    530         main_node.setAttribute("version", self.cansas_version) 
    531         main_node.setAttribute("xmlns", ns) 
    532         main_node.setAttribute("xmlns:xsi", 
    533                                "http://www.w3.org/2001/XMLSchema-instance") 
    534         if self.cansas_version == "1.0": 
    535             main_node.setAttribute("xsi:schemaLocation", "cansas1d/1.0 http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd") 
    536         elif self.cansas_version == "1.1": 
    537             main_node.setAttribute("xsi:schemaLocation", "urn:cansas1d:1.1 http://www.cansas.org/formats/1.1/cansas1d.xsd") 
    538          
    539         doc.appendChild(main_node) 
    540          
    541         entry_node = doc.createElement("SASentry") 
    542         main_node.appendChild(entry_node) 
    543          
    544         write_node(doc, entry_node, "Title", datainfo.title) 
     527        # Get PIs and create root element 
     528        pis = self.reader.return_processing_instructions() 
     529        doc = self.reader.create_tree(pis[0]) 
     530        i = 1 
     531        for i in range(1,len(pis) - 1): 
     532            doc = self.reader.append(pis[i], doc) 
     533         
     534        # Define namespaces and create SASroot object 
     535        xsi = "http://www.w3.org/2001/XMLSchema-instance" 
     536        version = self.cansas_version 
     537        ns = CANSAS_NS.get(version).get("ns") 
     538        if version == "1.1": 
     539            url = "http://www.cansas.org/formats/1.1/" 
     540        else: 
     541            url = "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/" 
     542        schemaLocation = "{0} {1}cansas1d.xsd".format(ns, url) 
     543        attrib = {"{" + xsi + "}schemaLocation" : schemaLocation, 
     544                  "version" : version} 
     545        nsmap = {'xsi' : xsi, None: ns} 
     546         
     547        main_node = self.reader.create_element("{" + ns + "}SASroot", \ 
     548                                               attrib = attrib, \ 
     549                                               nsmap = nsmap) 
     550         
     551        # Create ElementTree, append SASroot and apply processing instructions 
     552        base_string = self.reader.toString(doc) + \ 
     553                    self.reader.toString(main_node) 
     554        base_element = self.reader.create_element_from_string(base_string) 
     555        doc = self.reader.create_tree(base_element) 
     556         
     557        # Create SASentry Element 
     558        entry_node = self.reader.create_element("SASentry") 
     559        root = doc.getroot() 
     560        root.append(entry_node) 
     561         
     562        # Add Title to SASentry 
     563        self.write_node(entry_node, "Title", datainfo.title) 
     564         
     565        # Add Run to SASentry 
    545566        if datainfo.run == None or datainfo.run == []: 
    546567            RUN_NAME_DEFAULT = "None" 
     
    552573            len(str(datainfo.run_name[item])) > 1: 
    553574                runname = {'name': datainfo.run_name[item]} 
    554             write_node(doc, entry_node, "Run", item, runname) 
     575            self.write_node(entry_node, "Run", item, runname) 
    555576         
    556577        # Data info 
    557         node = doc.createElement("SASdata") 
    558         entry_node.appendChild(node) 
     578        node = self.reader.create_element("SASdata") 
     579        self.reader.append(node, entry_node) 
    559580         
    560581        for i in range(len(datainfo.x)): 
    561             pt = doc.createElement("Idata") 
    562             node.appendChild(pt) 
    563             write_node(doc, pt, "Q", datainfo.x[i], {'unit': datainfo.x_unit}) 
     582            pt = self.reader.create_element("Idata") 
     583            node.append(pt) 
     584            self.write_node(pt, "Q", datainfo.x[i], {'unit': datainfo.x_unit}) 
    564585            if len(datainfo.y) >= i: 
    565                 write_node(doc, pt, "I", datainfo.y[i], 
     586                self.write_node(pt, "I", datainfo.y[i], 
    566587                            {'unit': datainfo.y_unit}) 
    567588            if datainfo.dy != None and len(datainfo.dy) > i: 
    568                 write_node(doc, pt, "Idev", datainfo.dy[i], 
     589                self.write_node(pt, "Idev", datainfo.dy[i], 
    569590                            {'unit': datainfo.y_unit}) 
    570591            if datainfo.dx != None and len(datainfo.dx) > i: 
    571                 write_node(doc, pt, "Qdev", datainfo.dx[i], 
     592                self.write_node(pt, "Qdev", datainfo.dx[i], 
    572593                            {'unit': datainfo.x_unit}) 
    573594            if datainfo.dxw != None and len(datainfo.dxw) > i: 
    574                 write_node(doc, pt, "dQw", datainfo.dxw[i], 
     595                self.write_node(pt, "dQw", datainfo.dxw[i], 
    575596                            {'unit': datainfo.x_unit}) 
    576597            if datainfo.dxl != None and len(datainfo.dxl) > i: 
    577                 write_node(doc, pt, "dQl", datainfo.dxl[i], 
     598                self.write_node(pt, "dQl", datainfo.dxl[i], 
    578599                            {'unit': datainfo.x_unit}) 
    579600 
     
    581602        for i in range(len(datainfo.trans_spectrum)): 
    582603            spectrum = datainfo.trans_spectrum[i] 
    583             node = doc.createElement("SAStransmission_spectrum") 
    584             node.setAttribute("name", spectrum.name) 
     604            node = self.reader.create_element("SAStransmission_spectrum", 
     605                                              {"name" : spectrum.name}) 
     606            self.reader.append(node, entry_node) 
    585607            if isinstance(spectrum.timestamp, datetime.datetime): 
    586608                node.setAttribute("timestamp", spectrum.timestamp) 
    587             entry_node.appendChild(node) 
    588609            for i in range(len(spectrum.wavelength)): 
    589                 pt = doc.createElement("Tdata") 
    590                 node.appendChild(pt) 
    591                 write_node(doc, pt, "Lambda", spectrum.wavelength[i],  
     610                pt = self.reader.create_element("Tdata") 
     611                node.append(pt) 
     612                self.write_node(pt, "Lambda", spectrum.wavelength[i],  
    592613                           {'unit': spectrum.wavelength_unit}) 
    593                 write_node(doc, pt, "T", spectrum.transmission[i],  
     614                self.write_node(pt, "T", spectrum.transmission[i],  
    594615                           {'unit': spectrum.transmission_unit}) 
    595616                if spectrum.transmission_deviation != None \ 
    596617                and len(spectrum.transmission_deviation) >= i: 
    597                     write_node(doc, pt, "Tdev", \ 
     618                    self.write_node(pt, "Tdev", \ 
    598619                               spectrum.transmission_deviation[i], \ 
    599620                               {'unit': spectrum.transmission_deviation_unit}) 
    600621 
    601622        # Sample info 
    602         sample = doc.createElement("SASsample") 
     623        sample = self.reader.create_element("SASsample") 
    603624        if datainfo.sample.name is not None: 
    604             sample.setAttribute("name", str(datainfo.sample.name)) 
    605         entry_node.appendChild(sample) 
    606         write_node(doc, sample, "ID", str(datainfo.sample.ID)) 
    607         write_node(doc, sample, "thickness", datainfo.sample.thickness, 
     625            self.reader.write_attribute(sample,  
     626                                        "name",  
     627                                        str(datainfo.sample.name)) 
     628        self.reader.append(sample, entry_node) 
     629        self.write_node(sample, "ID", str(datainfo.sample.ID)) 
     630        self.write_node(sample, "thickness", datainfo.sample.thickness, 
    608631                   {"unit": datainfo.sample.thickness_unit}) 
    609         write_node(doc, sample, "transmission", datainfo.sample.transmission) 
    610         write_node(doc, sample, "temperature", datainfo.sample.temperature, 
     632        self.write_node(sample, "transmission", datainfo.sample.transmission) 
     633        self.write_node(sample, "temperature", datainfo.sample.temperature, 
    611634                   {"unit": datainfo.sample.temperature_unit}) 
    612635         
    613         pos = doc.createElement("position") 
    614         written = write_node(doc, pos, "x", datainfo.sample.position.x, 
    615                              {"unit": datainfo.sample.position_unit}) 
    616         written = written | write_node(doc, pos, "y", 
    617                                        datainfo.sample.position.y, 
     636        pos = self.reader.create_element("position") 
     637        written = self.write_node(pos,  
     638                                  "x",  
     639                                  datainfo.sample.position.x, 
     640                                  {"unit": datainfo.sample.position_unit}) 
     641        written = written | self.write_node(pos,  
     642                                            "y",  
     643                                            datainfo.sample.position.y, 
    618644                                       {"unit": datainfo.sample.position_unit}) 
    619         written = written | write_node(doc, pos, "z", 
    620                                        datainfo.sample.position.z, 
     645        written = written | self.write_node(pos,  
     646                                            "z", 
     647                                            datainfo.sample.position.z, 
    621648                                       {"unit": datainfo.sample.position_unit}) 
    622649        if written == True: 
    623             sample.appendChild(pos) 
    624          
    625         ori = doc.createElement("orientation") 
    626         written = write_node(doc, ori, "roll", 
    627                              datainfo.sample.orientation.x, 
    628                              {"unit": datainfo.sample.orientation_unit}) 
    629         written = written | write_node(doc, ori, "pitch", 
     650            self.reader.append(pos, sample) 
     651         
     652        ori = self.reader.create_element("orientation") 
     653        written = self.write_node(ori, "roll", 
     654                                  datainfo.sample.orientation.x, 
     655                                  {"unit": datainfo.sample.orientation_unit}) 
     656        written = written | self.write_node(ori, "pitch", 
    630657                                       datainfo.sample.orientation.y, 
    631658                                    {"unit": datainfo.sample.orientation_unit}) 
    632         written = written | write_node(doc, ori, "yaw", 
     659        written = written | self.write_node(ori, "yaw", 
    633660                                       datainfo.sample.orientation.z, 
    634661                                    {"unit": datainfo.sample.orientation_unit}) 
    635662        if written == True: 
    636             sample.appendChild(ori) 
     663            self.reader.append(ori, sample) 
    637664         
    638665        for item in datainfo.sample.details: 
    639             write_node(doc, sample, "details", item) 
     666            self.write_node(sample, "details", item) 
    640667         
    641668        # Instrument info 
    642         instr = doc.createElement("SASinstrument") 
    643         entry_node.appendChild(instr) 
    644          
    645         write_node(doc, instr, "name", datainfo.instrument) 
     669        instr = self.reader.create_element("SASinstrument") 
     670        self.reader.append(instr, entry_node) 
     671         
     672        self.write_node(instr, "name", datainfo.instrument) 
    646673         
    647674        #   Source 
    648         source = doc.createElement("SASsource") 
     675        source = self.reader.create_element("SASsource") 
    649676        if datainfo.source.name is not None: 
    650             source.setAttribute("name", str(datainfo.source.name)) 
    651         instr.appendChild(source) 
     677            self.reader.write_attribute(source, 
     678                                        "name", 
     679                                        str(datainfo.source.name)) 
     680        self.reader.append(source, instr) 
    652681        if datainfo.source.radiation == None or datainfo.source.radiation == '': 
    653682            datainfo.source.radiation = "neutron" 
    654         write_node(doc, source, "radiation", datainfo.source.radiation) 
    655          
    656         size = doc.createElement("beam_size") 
     683        self.write_node(source, "radiation", datainfo.source.radiation) 
     684         
     685        size = self.reader.create_element("beam_size") 
    657686        if datainfo.source.beam_size_name is not None: 
    658             size.setAttribute("name", str(datainfo.source.beam_size_name)) 
    659         written = write_node(doc, size, "x", datainfo.source.beam_size.x, 
     687            self.reader.write_attribute(size, 
     688                                        "name", 
     689                                        str(datainfo.source.beam_size_name)) 
     690        written = self.write_node(size, "x", datainfo.source.beam_size.x, 
    660691                             {"unit": datainfo.source.beam_size_unit}) 
    661         written = written | write_node(doc, size, "y", 
     692        written = written | self.write_node(size, "y", 
    662693                                       datainfo.source.beam_size.y, 
    663694                                       {"unit": datainfo.source.beam_size_unit}) 
    664         written = written | write_node(doc, size, "z", 
     695        written = written | self.write_node(size, "z", 
    665696                                       datainfo.source.beam_size.z, 
    666697                                       {"unit": datainfo.source.beam_size_unit}) 
    667698        if written == True: 
    668             source.appendChild(size) 
     699            self.reader.append(size, source) 
    669700             
    670         write_node(doc, source, "beam_shape", datainfo.source.beam_shape) 
    671         write_node(doc, source, "wavelength", 
     701        self.write_node(source, "beam_shape", datainfo.source.beam_shape) 
     702        self.write_node(source, "wavelength", 
    672703                   datainfo.source.wavelength, 
    673704                   {"unit": datainfo.source.wavelength_unit}) 
    674         write_node(doc, source, "wavelength_min", 
     705        self.write_node(source, "wavelength_min", 
    675706                   datainfo.source.wavelength_min, 
    676707                   {"unit": datainfo.source.wavelength_min_unit}) 
    677         write_node(doc, source, "wavelength_max", 
     708        self.write_node(source, "wavelength_max", 
    678709                   datainfo.source.wavelength_max, 
    679710                   {"unit": datainfo.source.wavelength_max_unit}) 
    680         write_node(doc, source, "wavelength_spread", 
     711        self.write_node(source, "wavelength_spread", 
    681712                   datainfo.source.wavelength_spread, 
    682713                   {"unit": datainfo.source.wavelength_spread_unit}) 
     
    687718            datainfo.collimation.append(coll) 
    688719        for item in datainfo.collimation: 
    689             coll = doc.createElement("SAScollimation") 
     720            coll = self.reader.create_element("SAScollimation") 
    690721            if item.name is not None: 
    691                 coll.setAttribute("name", str(item.name)) 
    692             instr.appendChild(coll) 
     722                self.reader.write_attribute(coll, "name", str(item.name)) 
     723            self.reader.append(coll, instr) 
    693724             
    694             write_node(doc, coll, "length", item.length, 
     725            self.write_node(coll, "length", item.length, 
    695726                       {"unit": item.length_unit}) 
    696727             
    697728            for apert in item.aperture: 
    698                 ap = doc.createElement("aperture") 
     729                ap = self.reader.create_element("aperture") 
    699730                if apert.name is not None: 
    700                     ap.setAttribute("name", str(apert.name)) 
     731                    self.reader.write_attribute(ap, "name", str(apert.name)) 
    701732                if apert.type is not None: 
    702                     ap.setAttribute("type", str(apert.type)) 
    703                 coll.appendChild(ap) 
    704                  
    705                 size = doc.createElement("size") 
     733                    self.reader.write_attribute(ap, "type", str(apert.type)) 
     734                self.reader.append(ap, coll) 
     735                 
     736                size = self.reader.create_element("size") 
    706737                if apert.size_name is not None: 
    707                     size.setAttribute("name", str(apert.size_name)) 
    708                 written = write_node(doc, size, "x", apert.size.x, 
     738                    self.reader.write_attribute(size,  
     739                                                "name",  
     740                                                str(apert.size_name)) 
     741                written = self.write_node(size, "x", apert.size.x, 
    709742                                     {"unit": apert.size_unit}) 
    710                 written = written | write_node(doc, size, "y", apert.size.y, 
     743                written = written | self.write_node(size, "y", apert.size.y, 
    711744                                               {"unit": apert.size_unit}) 
    712                 written = written | write_node(doc, size, "z", apert.size.z, 
     745                written = written | self.write_node(size, "z", apert.size.z, 
    713746                                               {"unit": apert.size_unit}) 
    714747                if written == True: 
    715                     ap.appendChild(size) 
    716                  
    717                 write_node(doc, ap, "distance", apert.distance, 
     748                    self.reader.append(size, ap) 
     749                 
     750                self.write_node(ap, "distance", apert.distance, 
    718751                           {"unit": apert.distance_unit}) 
    719752 
     
    725758                 
    726759        for item in datainfo.detector: 
    727             det = doc.createElement("SASdetector") 
    728             written = write_node(doc, det, "name", item.name) 
    729             written = written | write_node(doc, det, "SDD", item.distance, 
     760            det = self.reader.create_element("SASdetector") 
     761            written = self.write_node(det, "name", item.name) 
     762            written = written | self.write_node(det, "SDD", item.distance, 
    730763                                           {"unit": item.distance_unit}) 
    731764            if written == True: 
    732                 instr.appendChild(det) 
     765                self.reader.append(det, instr) 
    733766             
    734             off = doc.createElement("offset") 
    735             written = write_node(doc, off, "x", item.offset.x, 
     767            off = self.reader.create_element("offset") 
     768            written = self.write_node(off, "x", item.offset.x, 
    736769                                 {"unit": item.offset_unit}) 
    737             written = written | write_node(doc, off, "y", item.offset.y, 
     770            written = written | self.write_node(off, "y", item.offset.y, 
    738771                                           {"unit": item.offset_unit}) 
    739             written = written | write_node(doc, off, "z", item.offset.z, 
     772            written = written | self.write_node(off, "z", item.offset.z, 
    740773                                           {"unit": item.offset_unit}) 
    741774            if written == True: 
    742                 det.appendChild(off) 
    743                  
    744             ori = doc.createElement("orientation") 
    745             written = write_node(doc, ori, "roll", item.orientation.x, 
     775                self.reader.append(off, det) 
     776                 
     777            ori = self.reader.create_element("orientation") 
     778            written = self.write_node(ori, "roll", item.orientation.x, 
    746779                                 {"unit": item.orientation_unit}) 
    747             written = written | write_node(doc, ori, "pitch", 
     780            written = written | self.write_node(ori, "pitch", 
    748781                                           item.orientation.y, 
    749782                                           {"unit": item.orientation_unit}) 
    750             written = written | write_node(doc, ori, "yaw", 
     783            written = written | self.write_node(ori, "yaw", 
    751784                                           item.orientation.z, 
    752785                                           {"unit": item.orientation_unit}) 
    753786            if written == True: 
    754                 det.appendChild(ori) 
     787                self.reader.append(ori, det) 
    755788             
    756             center = doc.createElement("beam_center") 
    757             written = write_node(doc, center, "x", item.beam_center.x, 
     789            center = self.reader.create_element("beam_center") 
     790            written = self.write_node(center, "x", item.beam_center.x, 
    758791                                 {"unit": item.beam_center_unit}) 
    759             written = written | write_node(doc, center, "y", 
     792            written = written | self.write_node(center, "y", 
    760793                                           item.beam_center.y, 
    761794                                           {"unit": item.beam_center_unit}) 
    762             written = written | write_node(doc, center, "z", 
     795            written = written | self.write_node(center, "z", 
    763796                                           item.beam_center.z, 
    764797                                           {"unit": item.beam_center_unit}) 
    765798            if written == True: 
    766                 det.appendChild(center) 
    767                  
    768             pix = doc.createElement("pixel_size") 
    769             written = write_node(doc, pix, "x", item.pixel_size.x, 
     799                self.reader.append(center, det) 
     800                 
     801            pix = self.reader.create_element("pixel_size") 
     802            written = self.write_node(pix, "x", item.pixel_size.x, 
    770803                                 {"unit": item.pixel_size_unit}) 
    771             written = written | write_node(doc, pix, "y", item.pixel_size.y, 
     804            written = written | self.write_node(pix, "y", item.pixel_size.y, 
    772805                                           {"unit": item.pixel_size_unit}) 
    773             written = written | write_node(doc, pix, "z", item.pixel_size.z, 
     806            written = written | self.write_node(pix, "z", item.pixel_size.z, 
    774807                                           {"unit": item.pixel_size_unit}) 
    775             if written == True: 
    776                 det.appendChild(pix) 
    777             written = written | write_node(doc, det, "slit_length", 
     808            written = written | self.write_node(det, "slit_length", 
    778809                                           item.slit_length, 
    779810                                           {"unit": item.slit_length_unit}) 
     811            if written == True: 
     812                self.reader.append(pix, det) 
    780813             
    781814        # Processes info 
    782815        for item in datainfo.process: 
    783             node = doc.createElement("SASprocess") 
    784             entry_node.appendChild(node) 
    785  
    786             write_node(doc, node, "name", item.name) 
    787             write_node(doc, node, "date", item.date) 
    788             write_node(doc, node, "description", item.description) 
     816            node = self.reader.create_element("SASprocess") 
     817            self.reader.append(node, entry_node) 
     818 
     819            self.write_node(node, "name", item.name) 
     820            self.write_node(node, "date", item.date) 
     821            self.write_node(node, "description", item.description) 
    789822            for term in item.term: 
    790823                value = term['value'] 
    791824                del term['value'] 
    792                 write_node(doc, node, "term", value, term) 
     825                self.write_node(node, "term", value, term) 
    793826            for note in item.notes: 
    794                 write_node(doc, node, "SASprocessnote", note) 
     827                self.write_node(node, "SASprocessnote", note) 
    795828            if len(item.notes) == 0: 
    796                 write_node(doc, node, "SASprocessnote", "") 
     829                self.write_node(node, "SASprocessnote", "") 
    797830                 
    798831        # Note info 
    799832        if len(datainfo.notes) == 0: 
    800             node = doc.createElement("SASnote") 
    801             entry_node.appendChild(node) 
    802             if node.hasChildNodes(): 
    803                 for child in node.childNodes: 
    804                     node.removeChild(child) 
     833            node = self.reader.create_element("SASnote") 
     834            self.reader.append(node, entry_node) 
    805835        else: 
    806836            for item in datainfo.notes: 
    807                 node = doc.createElement("SASnote") 
    808                 entry_node.appendChild(node) 
    809                 node.appendChild(doc.createTextNode(item)) 
    810                  
     837                node = self.reader.create_element("SASnote") 
     838                self.reader.write_text(node, item) 
     839                self.reader.append(node, entry_node) 
     840                 
     841         
    811842        # Return the document, and the SASentry node associated with 
    812843        # the data we just wrote 
    813844        return doc, entry_node 
     845     
     846     
     847    def write_node(self, parent, name, value, attr={}): 
     848        """ 
     849        :param doc: document DOM 
     850        :param parent: parent node 
     851        :param name: tag of the element 
     852        :param value: value of the child text node 
     853        :param attr: attribute dictionary 
     854         
     855        :return: True if something was appended, otherwise False 
     856        """ 
     857        if value is not None: 
     858            parent = self.reader.ebuilder(parent, name, value, attr) 
     859            return True 
     860        return False 
     861     
    814862             
    815863    def write(self, filename, datainfo): 
     
    824872        # Write the file 
    825873        fd = open(filename, 'w') 
    826         fd.write(doc.toprettyxml()) 
     874        if self.reader.encoding == None: 
     875            self.reader.encoding = "UTF-8" 
     876        doc.write(fd, encoding=self.reader.encoding, 
     877                  pretty_print=True, xml_declaration=True) 
    827878        fd.close() 
    828879     
    829     ## Once I convert the writer to lxml from minidom 
    830     ## This can be moved into xml_reader 
    831     def setProcessingInstructions(self, minidomObject, dic): 
    832         xmlroot = minidomObject.firstChild 
    833         for item in dic: 
    834             pi = minidomObject.createProcessingInstruction(item, dic[item]) 
    835             minidomObject.insertBefore(pi, xmlroot) 
    836         return minidomObject 
    837      
  • src/sans/dataloader/readers/xml_reader.py

    rf44b076 r2e3b055  
    11""" 
    2     Generic XML reader 
     2    Generic XML read and write utility 
     3     
     4    Usage: Either extend xml_reader or add as a class variable. 
    35""" 
    46############################################################################ 
     
    1416 
    1517from lxml import etree 
     18from lxml.builder import E 
    1619parser = etree.ETCompatXMLParser(remove_comments=True, remove_pis=False) 
    1720 
     
    2326    schema = None 
    2427    schemadoc = None 
     28    encoding = None 
    2529    processingInstructions = None 
    2630     
     
    104108        self.setSchema(self.schema) 
    105109         
    106     def toString(self, etreeElement): 
    107         """ 
    108         Converts and etree element into a string 
    109         """ 
    110         return etree.tostring(etreeElement) 
     110    def toString(self, elem, pp=False, encoding=None): 
     111        """ 
     112        Converts an etree element into a string 
     113        """ 
     114        return etree.tostring(elem, pretty_print = pp, encoding = encoding) 
     115     
     116    def break_processing_instructions(self, string, dic): 
     117        """ 
     118        Method to break a processing instruction string apart and add to a dict 
     119         
     120        :param string: A processing instruction as a string 
     121        :param dic: The dictionary to save the PIs to 
     122        """ 
     123        pi_string = string.replace("<?", "").replace("?>", "") 
     124        split = pi_string.split(" ", 1) 
     125        pi_name = split[0] 
     126        attr = split[1] 
     127        new_pi_name = self._create_unique_key(dic, pi_name) 
     128        dic[new_pi_name] = attr 
     129        return dic 
    111130     
    112131    def setProcessingInstructions(self): 
    113132        """ 
    114133        Take out all processing instructions and create a dictionary from them 
     134        If there is a default encoding, the value is also saved 
    115135        """ 
    116136        dic = {} 
    117137        pi = self.xmlroot.getprevious() 
    118138        while pi is not None: 
    119             attr = {} 
    120             pi_name = "" 
    121139            pi_string = self.toString(pi) 
     140            if "?>\n<?" in pi_string: 
     141                pi_string = pi_string.split("?>\n<?") 
    122142            if isinstance(pi_string, str): 
    123                 pi_string = pi_string.replace("<?", "").replace("?>", "") 
    124                 split = pi_string.split(" ", 1) 
    125                 pi_name = split[0] 
    126                 attr = split[1] 
    127             new_pi_name = self._create_unique_key(dic, pi_name) 
    128             dic[new_pi_name] = attr 
     143                dic = self.break_processing_instructions(pi_string, dic) 
     144            elif isinstance(pi_string, list): 
     145                for item in pi_string: 
     146                    dic = self.break_processing_instructions(item, dic) 
    129147            pi = pi.getprevious() 
     148        if 'xml' in dic: 
     149            self.setEncoding(dic['xml']) 
     150            del dic['xml'] 
    130151        self.processingInstructions = dic 
     152         
     153    def setEncoding(self, attr_str): 
     154        """ 
     155        Find the encoding in the xml declaration and save it as a string 
     156         
     157        :param attr_str: All attributes as a string 
     158            e.g. "foo1="bar1" foo2="bar2" foo3="bar3" ... foo_n="bar_n"" 
     159        """ 
     160        attr_str = attr_str.replace(" = ", "=") 
     161        attr_list = attr_str.split( ) 
     162        for item in attr_list: 
     163            name_value = item.split("\"=") 
     164            name = name_value[0].lower() 
     165            value = name_value[1] 
     166            if name == "encoding": 
     167                self.encoding = value 
     168                return 
     169        self.encoding = None 
    131170         
    132171    def _create_unique_key(self, dictionary, name, i = 0): 
     
    148187    def create_tree(self, root): 
    149188        """ 
    150         Create an element tree for processing from an XML string 
    151          
    152         :param root: XML string  
     189        Create an element tree for processing from an etree element 
     190         
     191        :param root: etree Element(s)  
    153192        """ 
    154193        return etree.ElementTree(root) 
    155194     
    156     def create_element(self, name): 
     195    def create_element_from_string(self, s): 
     196        """ 
     197        Create an element from an XML string 
     198         
     199        :param s: A string of xml 
     200        """ 
     201        return etree.fromstring(s) 
     202     
     203    def create_element(self, name, attrib={}, nsmap=None): 
    157204        """ 
    158205        Create an XML element for writing to file 
     
    160207        :param name: The name of the element to be created 
    161208        """ 
    162         return etree.Element(name) 
     209        return etree.Element(name, attrib, nsmap) 
    163210     
    164211    def write_text(self, elem, text): 
     
    183230        attr[attr_name] = attr_value 
    184231         
     232    def return_processing_instructions(self): 
     233        """ 
     234        Get all processing instructions saved when loading the document 
     235         
     236        :param tree: etree.ElementTree object to write PIs to 
     237        """ 
     238        pi_list = [] 
     239        for key in self.processingInstructions: 
     240            value = self.processingInstructions.get(key) 
     241            pi = etree.ProcessingInstruction(key, value) 
     242            pi_list.append(pi) 
     243        return pi_list 
     244     
     245    def append(self, element, tree): 
     246        """ 
     247        Append an etree Element to an ElementTree. 
     248         
     249        :param element: etree Element to append 
     250        :param tree: ElementTree object to append to 
     251        """ 
     252        tree = tree.append(element) 
     253        return tree 
     254     
     255    def ebuilder(self, parent, elementname, text=None, attrib={}): 
     256        text = str(text) 
     257        elem = E(elementname, attrib, text) 
     258        parent = parent.append(elem) 
     259        return parent 
     260         
Note: See TracChangeset for help on using the changeset viewer.