/[thuban]/branches/WIP-pyshapelib-bramz/Extensions/wms/parser.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Extensions/wms/parser.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/Extensions/wms/parser.py revision 2133 by joey, Wed Mar 24 19:31:54 2004 UTC branches/WIP-pyshapelib-bramz/Extensions/wms/parser.py revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC
# Line 40  class WMSCapabilitiesParser: Line 40  class WMSCapabilitiesParser:
40      getLayerBBox(layer, srs)      getLayerBBox(layer, srs)
41    
42      isQueryable(layer)      isQueryable(layer)
   
     get_srs_discrepancies()  
43  """  """
44    
45  __version__ = "$Revision$"  __version__ = "$Revision$"
# Line 49  __version__ = "$Revision$" Line 47  __version__ = "$Revision$"
47  # $Id$  # $Id$
48    
49  import xml.dom.minidom  import xml.dom.minidom
50    from xml.dom import Node
51    
52  from domutils import getElementsByName, getElementByName  from domutils import getElementsByName, getElementByName
53    
54    from Thuban import _
55    
56  class WMSCapabilitiesParser:  class WMSCapabilitiesParser:
57      """      """
58      Thuban class to parse capabilities supplied as large string.      Thuban class to parse capabilities supplied as large string.
# Line 67  class WMSCapabilitiesParser: Line 68  class WMSCapabilitiesParser:
68      fees = None      fees = None
69      access = None      access = None
70      formats = None      formats = None
71      srs_discrepancies = None      error = None
72    
73    
74      def __init__(self):      def __init__(self):
# Line 78  class WMSCapabilitiesParser: Line 79  class WMSCapabilitiesParser:
79          # Note that we must not initialise internal variables of the          # Note that we must not initialise internal variables of the
80          # class in a mutable way or it will be shared among all          # class in a mutable way or it will be shared among all
81          # instances.  None is immutable, [] is not.          # instances.  None is immutable, [] is not.
82          layers = []          self.error = []
83    
84    
85      def grok(self, data):      def grok(self, data):
# Line 89  class WMSCapabilitiesParser: Line 90  class WMSCapabilitiesParser:
90          Information should only be retrieved with the respective          Information should only be retrieved with the respective
91          get*() methods.          get*() methods.
92          """          """
93          root = xml.dom.minidom.parseString(data).documentElement          xml_dom = xml.dom.minidom.parseString(data)
94            root = xml_dom.documentElement
95    
96          # Extract the title          # Extract the title
97          foo = getElementByName(getElementByName(root, 'Service'), 'Title')          foo = getElementByName(getElementByName(root, 'Service'), 'Title')
# Line 104  class WMSCapabilitiesParser: Line 106  class WMSCapabilitiesParser:
106          # Extract fees information          # Extract fees information
107          foo = getElementByName(getElementByName(root, 'Service'), 'Fees')          foo = getElementByName(getElementByName(root, 'Service'), 'Fees')
108          if foo and len(foo.childNodes[0].data) \          if foo and len(foo.childNodes[0].data) \
109                 and lower(foo.childNodes[0].data) != 'none':                 and foo.childNodes[0].data.lower() != 'none':
110              self.fees = foo.childNodes[0].data              self.fees = foo.childNodes[0].data
111                    
112          # Extract access information          # Extract access information
113          foo = getElementByName(getElementByName(root, 'Service'),          foo = getElementByName(getElementByName(root, 'Service'),
114                                 'AccessConstraints')                                 'AccessConstraints')
115          if foo and len(foo.childNodes[0].data) \          if foo and len(foo.childNodes[0].data) \
116                 and lower(foo.childNodes[0].data) != 'none':                 and foo.childNodes[0].data.lower() != 'none':
117              self.access = foo.childNodes[0].data              self.access = foo.childNodes[0].data
118                    
119          # Extract output format information          foo = getElementByName(getElementByName(
120          foo = getElementsByName(              root, 'Capability'), 'Request')
121              getElementByName(getElementByName(getElementByName(  
122              root, 'Capability'), 'Request'), 'GetMap'), 'Format')          # Need to distinguish between Map and GetMap for v1.0 and v1.1
123          self.formats = map((lambda i: i.childNodes[0].data), foo)          bar = getElementByName(foo, 'GetMap')
124            if bar:
125                # WMS 1.1
126                foo = getElementsByName(bar, 'Format')
127                self.formats = map((lambda i: i.childNodes[0].data), foo)
128            else:
129                # WMS 1.0
130                foo = getElementByName(getElementByName(
131                    foo, 'Map'), 'Format')
132                for node in foo.childNodes:
133                    if node.nodeType == Node.ELEMENT_NODE:
134                        try:
135                            self.formats.append(node.nodeName)
136                        except AttributeError:
137                            self.formats = [node.nodeName]
138    
139          # Extract layer names          # Extract layer names
140          self.layers = []          self.layers = []
141          self.peekLayers(getElementByName(getElementByName(          self.peekLayers(getElementByName(getElementByName(
142              root, 'Capability'), 'Layer'), -1)              root, 'Capability'), 'Layer'), -1)
143    
144            xml_dom.unlink()
145    
146    
147      def peekLayers(self, top, parent):      def peekLayers(self, top, parent):
148          """          """
# Line 149  class WMSCapabilitiesParser: Line 167  class WMSCapabilitiesParser:
167          foo = getElementByName(top, 'Title')          foo = getElementByName(top, 'Title')
168          if foo and len(foo.childNodes[0].data):          if foo and len(foo.childNodes[0].data):
169              self.layers[index]['title'] = foo.childNodes[0].data              self.layers[index]['title'] = foo.childNodes[0].data
170            else:
171                # A <Title> is required for each layer, <name> is optional
172                # See OGC 01-068r3, 7.1.4.5.1 and 7.1.4.5.2
173                self.error.append(_("No title found for layer #%d") % index)
174    
175          foo = getElementByName(top, 'Name')          foo = getElementByName(top, 'Name')
176          if foo and len(foo.childNodes[0].data):          if foo and len(foo.childNodes[0].data):
# Line 160  class WMSCapabilitiesParser: Line 182  class WMSCapabilitiesParser:
182                  if srs[0:5] == 'EPSG:':                  if srs[0:5] == 'EPSG:':
183                      srs = srs[5:]                      srs = srs[5:]
184                  try:                  try:
185                      self.layers[index]['srs'].append(srs)                      int(srs)
186                  except KeyError:                      try:
187                      self.layers[index]['srs'] = [srs]                          self.layers[index]['srs'].append(srs)
188                        except KeyError:
189                            self.layers[index]['srs'] = [srs]
190                    except ValueError:
191                        if srs[0:4].upper() == 'AUTO' \
192                               or srs[0:4].upper() == 'NONE':
193                            try:
194                                self.layers[index]['_srs_'].append(srs)
195                            except KeyError:
196                                self.layers[index]['_srs_'] = [srs]
197                        else:
198                            self.error.append(_("SRS '%s' is not numerical and not"
199                                                " AUTO/NONE in layer '%s'") \
200                                              % (srs, self.layers[index]['title']))
201    
202          foo = getElementByName(top, 'LatLonBoundingBox')          foo = getElementByName(top, 'LatLonBoundingBox')
203          if foo is not None:          if foo is not None:
# Line 183  class WMSCapabilitiesParser: Line 218  class WMSCapabilitiesParser:
218                  self.layers[index]['bbox'][srs][corner] \                  self.layers[index]['bbox'][srs][corner] \
219                      = foo.attributes.get(corner).nodeValue                      = foo.attributes.get(corner).nodeValue
220                            
         # Check for integrity  
         self.checkLayerSRS(index)  
   
221          # Traverse subsidiary layers          # Traverse subsidiary layers
222          sublayer = getElementsByName(top, 'Layer')          sublayer = getElementsByName(top, 'Layer')
223          for l in sublayer:          for l in sublayer:
224              self.peekLayers(l, index)              self.peekLayers(l, index)
225    
226    
     def checkLayerSRS(self, index):  
         """  
         Checks the integrity of the underlying XML data.  
   
         This is done by comparing the <SRS> elements with the  
         calculated list from the BoundingBox elements.  
   
         index -- position in the layers array to check  
         """  
   
         pivot = index  
         calculated = []  
         while pivot != -1:  
             if 'bbox' in self.layers[pivot]:  
                 for srs in self.layers[pivot]['bbox'].keys():  
                     if srs not in calculated:  
                         calculated.append(srs)  
             pivot = self.layers[pivot]['parent']  
   
         pivot = index  
         specified = []  
         while pivot != -1:  
             if 'srs' in self.layers[pivot]:  
                 for srs in self.layers[pivot]['srs']:  
                     if srs not in specified:  
                         specified.append(srs)  
             pivot = self.layers[pivot]['parent']  
   
         equal = True  
         # Check for same number of elements  
         if len(calculated) != len(specified):  
             equal = False  
   
         # Loop through all elements for existance  
         for elm in calculated:  
             if elm not in specified:  
                 equal = False  
   
         if not equal:  
             if self.srs_discrepancies is None:  
                 self.srs_discrepancies = []  
             if 'name' in self.layers[index]:  
                 id = "name:%s" % self.layers[index]['name']  
             else:  
                 id = "title:%s" % self.layers[index]['title']  
             self.srs_discrepancies.append(id)  
   
   
227      def getTitle(self):      def getTitle(self):
228          """          """
229          Returns the main title of the WMS object.          Returns the main title of the WMS object.
# Line 385  class WMSCapabilitiesParser: Line 369  class WMSCapabilitiesParser:
369          - Layers may optionally add to the global SRS list, or to the          - Layers may optionally add to the global SRS list, or to the
370            list inherited from a parent layer.            list inherited from a parent layer.
371    
372            - A server which has the ability to transform data to
373              different SRSes may choose not to provide an explicit
374              BoundingBox for every possible SRS available for each Layer.
375              Thus the list of <SRS> elements are authoritative.
376    
377          This implementation returns the list of SRS for the given          This implementation returns the list of SRS for the given
378          layer, calculated by looking at BoundingBoxes defined in the          layer, calculated by looking at BoundingBoxes defined in the
379          named layer and all layers higher in the hierarchy up to the          named layer and all layers higher in the hierarchy up to the
# Line 400  class WMSCapabilitiesParser: Line 389  class WMSCapabilitiesParser:
389    
390          result = []          result = []
391          while pivot != -1:          while pivot != -1:
392              if 'bbox' in self.layers[pivot]:              if 'srs' in self.layers[pivot]:
393                  for srs in self.layers[pivot]['bbox'].keys():                  for srs in self.layers[pivot]['srs']:
394                      if srs not in result:                      if srs not in result:
395                          result.append(srs)                          result.append(srs)
396              pivot = self.layers[pivot]['parent']              pivot = self.layers[pivot]['parent']
# Line 481  class WMSCapabilitiesParser: Line 470  class WMSCapabilitiesParser:
470                              if srs in pivot['bbox']:                              if srs in pivot['bbox']:
471                                  return pivot['bbox'][srs]                                  return pivot['bbox'][srs]
472    
473            # No matching BBox found, let's see if it was EPSG:4326
474            if srs == '4326':
475                return self.getLayerLatLonBBox(name)
476    
477          return None          return None
478    
479    
# Line 511  class WMSCapabilitiesParser: Line 504  class WMSCapabilitiesParser:
504          return 0          return 0
505    
506    
     def get_srs_discrepancies(self):  
         """  
         Returns a list of layer identifications where the denoted SRS  
         values differ from the calculated ones through BoundingBox  
         elements.  
         """  
         return self.srs_discrepancies  
   
507    
508  if __name__ == "__main__":  if __name__ == "__main__":
509      print "This module cannot be executed standalone."      print "This module cannot be executed standalone."
510    
511      import os      import os
512    
513        sample = "test/sample.xml"
514      try:      try:
515          f = open("test/sample.xml", "r")          f = open(sample, "r")
516      except IOError:      except IOError:
517          try:          try:
518              f = open(os.path.dirname(__file__) + "/test/sample.xml", "r")              f = open(os.path.dirname(__file__) + "/" + sample, "r")
519          except IOError:          except IOError:
520              print "Cannot open sample.xml for reading"              print "Cannot open %s for reading" % sample
521    
522      if f is not None:      if f is not None:
523          sample = f.read();          sample = f.read();

Legend:
Removed from v.2133  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26