Changeset 5009


Ignore:
Timestamp:
Feb 8, 2008, 1:34:51 PM (17 years ago)
Author:
ole
Message:

First cut of XML object model done. Three tests demonstrate the idea

Location:
anuga_core/source/anuga/utilities
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/utilities/test_xml_tools.py

    r5008 r5009  
    2222        """
    2323
    24         elements = []
     24           
     25        X1 = XML_element(tag='first element',
     26                         value=XML_element(tag='some text',
     27                                           value='hello world'))
     28
     29        text_elements = []
    2530        for i in range(10):
    2631            X = XML_element(tag='title %d' %i,
    27                             contents='example text %d' %i)
    28             elements.append(X)
     32                            value='example text %d' %i)
     33            text_elements.append(X)
    2934
    30            
    31         X1 = XML_element(tag='first element',
    32                          contents=XML_element(tag='some text',
    33                                               contents='hello world'))
    3435       
    3536        X2 = XML_element(tag='second element',
    36                          contents=XML_element(tag='texts',
    37                                               contents=elements))
     37                         value=XML_element(tag='texts',
     38                                           value=text_elements))
    3839        X3 = XML_element(tag='third element',
    39                          contents='42')       
     40                         value='42')       
    4041       
    4142           
    4243
    43         X = XML_element(tag='all',
    44                         contents=[X1, X2, X3])
    45         doc = XML_document(contents=X)
     44        doc = XML_element(value=[X1, X2, X3])
    4645
    4746        #print doc.pretty_print()       
    4847        #print doc
    49         assert doc['all']['second element']['texts']['title 4'].elements == 'example text 4'
     48
     49        assert doc['second element']['texts']['title 4'] == 'example text 4'
     50       
     51       
    5052
    5153       
     
    113115            xmlobject['ga_license_file'][tag]
    114116
    115         assert xmlobject['ga_license_file']['datafile']['accountable'].elements == 'Jane Sexton'
    116        
     117        assert xmlobject['ga_license_file']['datafile']['accountable'] == 'Jane Sexton'
    117118
    118119        #print
    119         #print
     120        #print xmlobject['ga_license_file']['datafile']
    120121        #print xmlobject['ga_license_file']['metadata']
    121122        #print xmlobject['ga_license_file']['datafile']
    122123        #print xmlobject['ga_license_file']['datafile']['accountable']       
    123 
    124         #print xmlobject['ga_license_file'].keys()
     124        #print xmlobject['ga_license_file']['datafile'].keys()
    125125
    126126        #for tag in xmlobject['ga_license_file'].keys():
     
    128128               
    129129        # Clean up
     130        os.remove(tmp_name)
    130131        fid.close()
    131132
    132133       
    133134
     135    def test_generate_and_read_back(self):
     136        """Test that xml code generated from XMLobject model
     137        can be read back.
     138        """
     139
     140           
     141        X1 = XML_element(tag='first_element',
     142                         value=XML_element(tag='some_text',
     143                                           value='hello world'))
     144
     145        text_elements = []
     146        for i in range(10):
     147            X = XML_element(tag='title_%d' %i,
     148                            value='example text %d' %i)
     149            text_elements.append(X)
     150
     151       
     152        X2 = XML_element(tag='second_element',
     153                         value=XML_element(tag='texts',
     154                                           value=text_elements))
     155        X3 = XML_element(tag='third_element',
     156                         value='42')       
     157       
     158           
     159        # Need to have one main element according to minidom
     160        main = XML_element(tag='all', value=[X1, X2, X3])
     161        xmldoc = XML_element(value=main)
     162        #print xmldoc
     163
     164        tmp_fd , tmp_name = mkstemp(suffix='.xml', dir='.')
     165        fid = os.fdopen(tmp_fd, 'w')
     166
     167        fid.write(str(xmldoc))
     168        fid.close()
     169
     170        # Now read it back
     171        xmlobject = xml2object(tmp_name, verbose=True)       
     172        #print xmlobject
     173
     174        assert str(xmldoc) == str(xmlobject)
     175
     176        os.remove(tmp_name)
    134177       
    135178#-------------------------------------------------------------
  • anuga_core/source/anuga/utilities/xml_tools.py

    r5008 r5009  
    7171
    7272class XML_element(dict):
    73     def __init__(self, tag=None, contents=None):
    74         """
    75         contents can be either
     73    def __init__(self,
     74                 tag=None,
     75                 value=None,
     76                 version='1.0',
     77                 encoding='iso-8859-1'):                 
     78        """
     79        value can be either
    7680          * An XML_element
    77           * a list of XML_elements
     81          * a list of XML_value
    7882          * a text string
    7983       
    8084        """
    8185       
    82         if isinstance(contents, XML_element):
    83             contents = [contents]
    84            
    85         self.elements = contents
     86        if isinstance(value, XML_element):
     87            value = [value]
     88           
     89        self.value = value
     90
     91
     92
     93        if tag is None:
     94            tag = '?xml version="%s" encoding="%s"?' %(version, encoding)
     95            self.root_element = True
     96        else:
     97            self.root_element = False
     98       
    8699        self.tag = tag
     100
     101
     102
     103       
    87104        # FIXME: It might be better to represent these objects
    88105        # in a proper dictionary format with
    89         # {tag: elements, ...}
     106        # {tag: value, ...}
     107        # No, tried that - it removes any notion of ordering.
    90108       
    91109
     
    100118
    101119    def __str__(self, indent=0):
    102 
     120        """String representation of XML element
     121        """
     122
     123        if self.root_element is True:
     124            increment = 0
     125        else:
     126            increment = 4
     127           
    103128        s = tab = ' '*indent
    104129       
    105130        s += '<%s>' %self.tag
    106         if isinstance(self.elements, basestring):
    107             s += self.elements
     131        if isinstance(self.value, basestring):
     132            s += self.value
    108133        else:
    109134            s += '\n'
    110             for e in self.elements:
    111                 s += e.__str__(indent+4)
     135            for e in self.value:
     136                s += e.__str__(indent+increment)
    112137            s += tab
    113138
    114         s += '</%s>\n' %self.tag
     139        if self.root_element is False:   
     140            s += '</%s>\n' %self.tag
     141           
    115142        return s
    116143
     
    118145    def __getitem__(self, key):
    119146        """Return sub-tree starting at element with tag equal to specified key
    120         """
    121 
    122         #if isinstance(self, XML_element):
    123         for node in self.elements:
     147        If node is terminal, its text value will be returned instead of itself.
     148        This will allow statements such as
     149
     150        assert xmlobject['datafile']['accountable'] == 'Jane Sexton'       
     151        """
     152
     153        for node in self.value:
    124154            if node.tag == key:
    125                 return node
     155                if isinstance(node.value, basestring):
     156                    return node.value
     157                else:
     158                    return node
    126159
    127160    def keys(self):
    128         return [str(node.tag) for node in self.elements]
     161        return [str(node.tag) for node in self.value]
    129162
    130163   
     
    136169        s = tab = ' '*indent
    137170        s += '%s: ' %self.tag       
    138         if isinstance(self.elements, basestring):
    139             s += self.elements
     171        if isinstance(self.value, basestring):
     172            s += self.value
    140173        else:
    141174            s += '\n'
    142             for e in self.elements:
     175            for e in self.value:
    143176                s += e.pretty_print(indent+4)
    144177        s += '\n'
     
    147180   
    148181   
    149    
    150 class XML_document(XML_element):
    151 
    152     def __init__(self, contents=None, version='1.0', encoding='iso-8859-1'):
    153         tag = '?xml version="%s" encoding="%s"?' %(version, encoding)
    154 
    155         XML_element.__init__(self,
    156                              tag=tag,
    157                              contents=contents)
    158 
    159 
    160     def __str__(self):
    161         """Generate XML representation for use with xml2object function
    162         """
    163         s = '<%s>\n' %self.tag
    164         for e in self.elements:
    165             s += str(e)
    166 
    167         return s
    168 
    169     def pretty_print(self):
    170         s = ''
    171         for e in self.elements:
    172             s += e.pretty_print()
    173 
    174         return s
    175 
    176 
    177182def xml2object(xml, verbose=False):
    178183    """Generate XML object model from XML file or XML text
    179184
    180     This is the inverse operation to the __str__ representation.
     185    This is the inverse operation to the __str__ representation
     186    (up to whitespace).
    181187
    182188    Input xml can be either an
    183     * xml string ??
    184189    * xml file
    185190    * open xml file object
     
    188193    """
    189194
    190     #FIXME(Ole): Do the input tests
    191     #Assume open file object for now
    192 
    193     #fid = open(xml)
    194     dom = parse(xml)
     195    # FIXME - can we allow xml to be string?
     196    # This would depend on minidom's parse function
     197
     198    # Input tests
     199    if isinstance(xml, basestring):
     200        fid = open(xml)
     201    else:
     202        fid = xml
     203
     204    #print fid.read()   
     205    dom = parse(fid)
    195206
    196207    return dom2object(dom)
     
    202213    """
    203214
    204     contents = []
     215    value = []
    205216    for n in node.childNodes:
    206217
     
    223234                continue
    224235           
    225             contents = x
    226         else:
    227             contents.append(dom2object(n))
     236            value = x
     237        else:
     238            value.append(dom2object(n))
    228239
    229240
     
    231242
    232243    if node.nodeType == 9:
    233         # Document root
    234         X = XML_document(contents=contents)
     244        # Root node (document)
     245        tag = None
    235246    else:
    236         # Node
    237         X = XML_element(tag=node.nodeName,
    238                         contents=contents)
     247        # Normal XML node
     248        tag = node.nodeName
     249
     250       
     251    X = XML_element(tag=tag,
     252                    value=value)
    239253       
    240254    return X
Note: See TracChangeset for help on using the changeset viewer.