Package sld
[hide private]
[frames] | no frames]

Source Code for Package sld

   1  """ 
   2  StyledLayerDescriptor library for generating SLD documents. 
   3   
   4  SLD documents are used to style cartographic representations of geometric 
   5  features in most professional and desktop GIS applications. 
   6   
   7  Specification 
   8  ============= 
   9  The SLD specification is available from the Open Geospatial Consortium, 
  10  at U{http://www.opengeospatial.org/standards/sld} 
  11   
  12  License 
  13  ======= 
  14  Copyright 2011 David Zwarg <U{dzwarg@azavea.com}> 
  15   
  16  Licensed under the Apache License, Version 2.0 (the "License"); 
  17  you may not use this file except in compliance with the License. 
  18  You may obtain a copy of the License at 
  19   
  20  U{http://www.apache.org/licenses/LICENSE-2.0} 
  21   
  22  Unless required by applicable law or agreed to in writing, software 
  23  distributed under the License is distributed on an "AS IS" BASIS, 
  24  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  25  See the License for the specific language governing permissions and 
  26  limitations under the License. 
  27   
  28  @author: David Zwarg 
  29  @contact: dzwarg@azavea.com 
  30  @copyright: 2011, Azavea 
  31  @license: Apache 2.0 
  32  @version: 1.0.6 
  33  @newfield prop: Property, Properties 
  34  """ 
  35  from lxml.etree import parse, Element, XMLSchema, XMLSyntaxError, tostring 
  36  import urllib2 
  37  from tempfile import NamedTemporaryFile 
  38  import os, copy, logging 
39 40 -class SLDNode(object):
41 """ 42 A base class for all python objects that relate directly to SLD elements. 43 An SLDNode contains references to the underlying parent node, underlying 44 element node, and the namespace map. 45 46 The SLDNode base class also contains utility methods to construct properties 47 for child SLDNode objects. 48 """ 49 50 _nsmap = { 51 'sld':"http://www.opengis.net/sld", 52 'ogc':"http://www.opengis.net/ogc", 53 'xlink':"http://www.w3.org/1999/xlink", 54 'xsi':"http://www.w3.org/2001/XMLSchema-instance" 55 } 56 """Defined namespaces in SLD documents.""" 57
58 - def __init__(self, parent, descendant=True):
59 """ 60 Create a new SLDNode. It is not necessary to call this directly, because 61 all child classes should initialize the SLDNode internally. 62 63 @type parent: L{SLDNode} 64 @param parent: The parent class object. 65 @type descendant: boolean 66 @param descendant: Does this element descend from the parent, or is it a sibling? 67 """ 68 if parent is None: 69 self._parent = None 70 elif descendant: 71 self._parent = parent._node 72 else: 73 self._parent = parent._parent 74 self._node = None
75 76 @staticmethod
77 - def makeproperty(ns, cls=None, name=None, docstring='', descendant=True):
78 """ 79 Make a property on an instance of an SLDNode. If cls is omitted, the 80 property is assumed to be a text node, with no corresponding class 81 object. If name is omitted, the property is assumed to be a complex 82 node, with a corresponding class wrapper. 83 84 @type ns: string 85 @param ns: The namespace of this property's node. 86 @type cls: class 87 @param cls: Optional. The class of the child property. 88 @type name: string 89 @param name: Optional. The name of the child property. 90 @type docstring: string 91 @param docstring: Optional. The docstring to attach to the new property. 92 @type descendant: boolean 93 @param descendant: Does this element descend from the parent, or is it a sibling? 94 95 @rtype: property attribute 96 @return: A property attribute for this named property. 97 """ 98 def get_property(self): 99 """ 100 A generic property getter. 101 """ 102 if cls is None: 103 xpath = '%s:%s' % (ns, name) 104 else: 105 xpath = '%s:%s' % (ns, cls.__name__) 106 107 xpath = self._node.xpath(xpath, namespaces=SLDNode._nsmap) 108 if len(xpath) == 1: 109 if cls is None: 110 return xpath[0].text 111 else: 112 elem = cls.__new__(cls) 113 cls.__init__(elem, self, descendant=descendant) 114 return elem 115 else: 116 return None
117 118 def set_property(self, value): 119 """ 120 A generic property setter. 121 """ 122 if cls is None: 123 xpath = '%s:%s' % (ns, name) 124 else: 125 xpath = '%s:%s' % (ns, cls.__name__) 126 127 xpath = self._node.xpath(xpath, namespaces=SLDNode._nsmap) 128 if len(xpath) == 1: 129 if cls is None: 130 xpath[0].text = value 131 else: 132 xpath[0] = value._node 133 else: 134 if cls is None: 135 elem = self._node.makeelement('{%s}%s' % (SLDNode._nsmap[ns], name), nsmap=SLDNode._nsmap) 136 elem.text = value 137 self._node.append(elem) 138 else: 139 self._node.append(value._node)
140 141 def del_property(self): 142 """ 143 A generic property deleter. 144 """ 145 if cls is None: 146 xpath = '%s:%s' % (ns, name) 147 else: 148 xpath = '%s:%s' % (ns, cls.__name__) 149 150 xpath = self._node.xpath(xpath, namespaces=SLDNode._nsmap) 151 if len(xpath) == 1: 152 self._node.remove(xpath[0]) 153 154 return property(get_property, set_property, del_property, docstring) 155 156
157 - def get_or_create_element(self, ns, name):
158 """ 159 Attempt to get the only child element from this SLDNode. If the node 160 does not exist, create the element, attach it to the DOM, and return 161 the class object that wraps the node. 162 163 @type ns: string 164 @param ns: The namespace of the new element. 165 @type name: string 166 @param name: The name of the new element. 167 @rtype: L{SLDNode} 168 @return: The wrapped node, in the parent's property class. This will 169 always be a descendent of SLDNode. 170 """ 171 if len(self._node.xpath('%s:%s' % (ns, name), namespaces=SLDNode._nsmap)) == 1: 172 return getattr(self, name) 173 174 return self.create_element(ns, name)
175
176 - def create_element(self, ns, name):
177 """ 178 Create an element as a child of this SLDNode. 179 180 @type ns: string 181 @param ns: The namespace of the new element. 182 @type name: string 183 @param name: The name of the new element. 184 @rtype: L{SLDNode} 185 @return: The wrapped node, in the parent's property class. This will 186 always be a descendent of SLDNode. 187 """ 188 elem = self._node.makeelement('{%s}%s' % (SLDNode._nsmap[ns], name), nsmap=SLDNode._nsmap) 189 self._node.append(elem) 190 191 return getattr(self, name)
192
193 194 -class CssParameter(SLDNode):
195 """ 196 A css styling parameter. May be a child of L{Fill}, L{Font}, and L{Stroke}. 197 """
198 - def __init__(self, parent, index, descendant=True):
199 """ 200 Create a new CssParameter from an existing StyleItem. 201 202 @type parent: L{StyleItem} 203 @param parent: The parent class object. 204 @type index: integer 205 @param index: The index of the node in the list of all CssParameters in the parent. 206 @type descendant: boolean 207 @param descendant: Does this element descend from the parent, or is it a sibling? 208 """ 209 super(CssParameter, self).__init__(parent, descendant=descendant) 210 self._node = self._parent.xpath('sld:CssParameter', namespaces=SLDNode._nsmap)[index]
211
212 - def get_name(self):
213 """ 214 Get the name attribute. 215 216 @rtype: string 217 @return: The value of the 'name' attribute. 218 """ 219 return self._node.attrib['name']
220
221 - def set_name(self, value):
222 """ 223 Set the name attribute. 224 225 @type value: string 226 @param value: The value of the 'name' attribute. 227 """ 228 self._node.attrib['name'] = value
229
230 - def del_name(self):
231 """ 232 Delete the name attribute. 233 """ 234 del self._node.attrib['name']
235 236 Name = property(get_name, set_name, del_name, "The value of the 'name' attribute.") 237 """The value of the 'name' attribute.""" 238
239 - def get_value(self):
240 """ 241 Get the text content. 242 243 @rtype: string 244 @return: The text content. 245 """ 246 return self._node.text
247
248 - def set_value(self, value):
249 """ 250 Set the text content. 251 252 @type value: string 253 @param value: The text content. 254 """ 255 self._node.text = value
256
257 - def del_value(self):
258 """ 259 Delete the text content. 260 """ 261 self._node.clear()
262 263 Value = property(get_value, set_value, del_value, "The value of the parameter.") 264 """The value of the parameter."""
265
266 267 -class CssParameters(SLDNode):
268 """ 269 A collection of L{CssParameter} nodes. This is a pythonic helper (list of 270 nodes) that does not correspond to a true element in the SLD spec. 271 """
272 - def __init__(self, parent):
273 """ 274 Create a new list of CssParameters from the specified parent node. 275 276 @type parent: L{StyleItem} 277 @param parent: The parent class item. 278 """ 279 super(CssParameters, self).__init__(parent) 280 self._node = None 281 self._nodes = self._parent.xpath('sld:CssParameter', namespaces=SLDNode._nsmap)
282
283 - def __len__(self):
284 """ 285 Get the number of L{CssParameter} nodes in this list. 286 287 @rtype: integer 288 @return: The number of L{CssParameter} nodes. 289 """ 290 return len(self._nodes)
291
292 - def __getitem__(self, key):
293 """ 294 Get one of the L{CssParameter} nodes in the list. 295 296 @type key: integer 297 @param key: The index of the child node. 298 @rtype: L{CssParameter} 299 @return: The specific L{CssParameter} node. 300 """ 301 return CssParameter(self, key, descendant=False)
302
303 - def __setitem__(self, key, value):
304 """ 305 Set one of the L{CssParameter} nodes in the list with a new value. 306 307 @type key: integer 308 @param key: The index of the child node. 309 @type value: L{CssParameter}, etree.Element 310 @param value: The new value of the specific child node. 311 """ 312 if isinstance(value, CssParameter): 313 self._nodes.replace(self._nodes[key], value._node) 314 elif isinstance(value, Element): 315 self._nodes.replace(self._nodes[key], value)
316
317 - def __delitem__(self, key):
318 """ 319 Delete one of the L{CssParameter} nodes from the list. 320 321 @type key: integer 322 @param key: The index of the child node. 323 """ 324 self._nodes.remove(self._nodes[key])
325
326 327 -class StyleItem(SLDNode):
328 """ 329 Abstract base class for all nodes that contain a list of L{CssParameter} nodes. 330 """
331 - def __init__(self, parent, name, descendant=True):
332 """ 333 Create a new StyleItem. 334 335 @type parent: L{Symbolizer} 336 @param parent: The parent class object. 337 @type name: string 338 @param name: The name of the node. 339 @type descendant: boolean 340 @param descendant: Does this element descend from the parent, or is it a sibling? 341 """ 342 super(StyleItem, self).__init__(parent, descendant=descendant) 343 xpath = self._parent.xpath('sld:'+name, namespaces=SLDNode._nsmap) 344 if len(xpath) < 1: 345 self._node = self._parent.makeelement('{%s}%s' % (SLDNode._nsmap['sld'], name), nsmap=SLDNode._nsmap) 346 self._parent.append(self._node) 347 else: 348 self._node = xpath[0]
349 350 @property
351 - def CssParameters(self):
352 """ 353 Get the list of L{CssParameter} nodes in a friendly L{CssParameters} helper list. 354 355 @rtype: L{CssParameters} 356 @return: A pythonic list of L{CssParameter} children. 357 """ 358 return CssParameters(self)
359
360 - def create_cssparameter(self, name=None, value=None):
361 """ 362 Create a new L{CssParameter} node as a child of this element, and attach it to the DOM. 363 Optionally set the name and value of the parameter, if they are both provided. 364 365 @type name: string 366 @param name: Optional. The name of the L{CssParameter} 367 @type value: string 368 @param value: Optional. The value of the L{CssParameter} 369 @rtype: L{CssParameter} 370 @return: A new style parameter, set to the name and value. 371 """ 372 elem = self._node.makeelement('{%s}CssParameter' % SLDNode._nsmap['sld'], nsmap=SLDNode._nsmap) 373 self._node.append(elem) 374 375 if not (name is None or value is None): 376 elem.attrib['name'] = name 377 elem.text = value 378 379 return CssParameter(self, len(self._node)-1)
380
381 382 -class Fill(StyleItem):
383 """ 384 A style specification for fill types. This class contains a 385 L{CssParameters} list, which can include: 386 387 - fill 388 - fill-opacity 389 390 This class is a property of any L{Symbolizer}. 391 """
392 - def __init__(self, parent, descendant=True):
393 """ 394 Create a new Fill node from the specified parent. 395 396 @type parent: L{Symbolizer} 397 @param parent: The parent class object. 398 @type descendant: boolean 399 @param descendant: A flag indicating if this is a descendant node of the parent. 400 """ 401 super(Fill, self).__init__(parent, 'Fill', descendant=descendant)
402
403 404 -class Font(StyleItem):
405 """ 406 A style specification for font types. This class contains a 407 L{CssParameters} list, which can include: 408 409 - font-family 410 - font-size 411 - font-style 412 - font-weight 413 414 This class is a property of any L{Symbolizer}. 415 """
416 - def __init__(self, parent, descendant=True):
417 """ 418 Create a new Font node from the specified parent. 419 420 @type parent: L{Symbolizer} 421 @param parent: The parent class object. 422 @type descendant: boolean 423 @param descendant: A flag indicating if this is a descendant node of the parent. 424 """ 425 super(Font, self).__init__(parent, 'Font', descendant=descendant)
426
427 428 -class Stroke(StyleItem):
429 """ 430 A style specification for stroke types. This class contains a 431 L{CssParameters} list, which can include: 432 433 - stroke 434 - stroke-dasharray 435 - stroke-dashoffset 436 - stroke-linecap 437 - stroke-linejoin 438 - stroke-opacity 439 - stroke-width 440 441 This class is a property of any L{Symbolizer}. 442 """
443 - def __init__(self, parent, descendant=True):
444 """ 445 Create a new Stroke node from the specified parent. 446 447 @type parent: L{Symbolizer} 448 @param parent: The parent class object. 449 @type descendant: boolean 450 @param descendant: A flag indicating if this is a descendant node of the parent. 451 """ 452 super(Stroke, self).__init__(parent, 'Stroke', descendant=descendant)
453
454 455 -class Symbolizer(SLDNode):
456 """ 457 Abstract base class for all symbolizer nodes. Symbolizer nodes are those 458 that contain L{Fill}, L{Font}, or L{Stroke} children. 459 460 All derived Symbolizer classes have access to the Fill, Font, and Stroke properties. 461 462 @prop: B{Fill} 463 464 The element that contains the L{CssParameter} nodes for describing the polygon fill styles. 465 466 I{Type}: L{Fill} 467 468 @prop: B{Font} 469 470 The element that contains the L{CssParameter} nodes for describing the font styles. 471 472 I{Type}: L{Font} 473 474 @prop: B{Stroke} 475 476 The element that contains the L{CssParameter} nodes for describing the line styles. 477 478 I{Type}: L{Stroke} 479 """
480 - def __init__(self, parent, name, descendant=True):
481 """ 482 Create a new Symbolizer node. If the specified node is not found in the 483 DOM, the node will be created and attached to the parent. 484 485 @type parent: L{Rule} 486 @param parent: The parent class object. 487 @type name: string 488 @param name: The type of symbolizer node. If this parameter ends with 489 the character '*', the '*' will get expanded into 'Symbolizer'. 490 @type descendant: boolean 491 @param descendant: A flag indicating if this is a descendant node of the parent. 492 """ 493 super(Symbolizer, self).__init__(parent, descendant=descendant) 494 495 if name[len(name)-1] == '*': 496 name = name[0:-1] + 'Symbolizer' 497 498 xpath = self._parent.xpath('sld:%s' % name, namespaces=SLDNode._nsmap) 499 if len(xpath) < 1: 500 self._node = self._parent.makeelement('{%s}%s' % (SLDNode._nsmap['sld'], name), nsmap=SLDNode._nsmap) 501 self._parent.append(self._node) 502 else: 503 self._node = xpath[0] 504 505 setattr(self.__class__, 'Fill', SLDNode.makeproperty('sld', cls=Fill, 506 docstring="The parameters for describing the fill styling.")) 507 setattr(self.__class__, 'Font', SLDNode.makeproperty('sld', cls=Font, 508 docstring="The parameters for describing the font styling.")) 509 setattr(self.__class__, 'Stroke', SLDNode.makeproperty('sld', cls=Stroke, 510 docstring="The parameters for describing the stroke styling."))
511
512 - def create_fill(self):
513 """ 514 Create a new L{Fill} element on this Symbolizer. 515 516 @rtype: L{Fill} 517 @return: A new fill element, attached to this symbolizer. 518 """ 519 return self.create_element('sld', 'Fill')
520
521 - def create_font(self):
522 """ 523 Create a new L{Font} element on this Symbolizer. 524 525 @rtype: L{Font} 526 @return: A new font element, attached to this symbolizer. 527 """ 528 return self.create_element('sld', 'Font')
529
530 - def create_stroke(self):
531 """ 532 Create a new L{Stroke} element on this Symbolizer. 533 534 @rtype: L{Stroke} 535 @return: A new stroke element, attached to this symbolizer. 536 """ 537 return self.create_element('sld', 'Stroke')
538
539 540 -class PolygonSymbolizer(Symbolizer):
541 """ 542 A symbolizer for polygon geometries. A PolygonSymbolizer is a child of a 543 L{Rule} element. 544 545 @prop: Fill 546 547 The element that contains the L{CssParameter} nodes for describing the 548 polygon fill styles. 549 550 I{Type}: L{Fill} 551 552 @prop: Stroke 553 554 The element that contains the L{CssParameter} nodes for describing the line 555 styles. 556 557 I{Type}: L{Stroke} 558 """
559 - def __init__(self, parent, descendant=True):
560 """ 561 Create a new PolygonSymbolizer node, as a child of the specified parent. 562 563 @type parent: L{Rule} 564 @param parent: The parent class object. 565 @type descendant: boolean 566 @param descendant: A flag indicating if this is a descendant node of the parent. 567 """ 568 super(PolygonSymbolizer, self).__init__(parent, 'Polygon*', descendant)
569
570 571 -class LineSymbolizer(Symbolizer):
572 """ 573 A symbolizer for line geometries. A LineSymbolizer is a child of a 574 L{Rule} element. 575 576 @prop: Stroke 577 578 The element that contains the L{CssParameter} nodes for describing the line 579 styles. 580 581 I{Type}: L{Stroke} 582 """
583 - def __init__(self, parent, descendant=True):
584 """ 585 Create a new LineSymbolizer node, as a child of the specified parent. 586 587 @type parent: L{Rule} 588 @param parent: The parent class object. 589 @type descendant: boolean 590 @param descendant: A flag indicating if this is a descendant node of the parent. 591 """ 592 super(LineSymbolizer, self).__init__(parent, 'Line*', descendant)
593
594 595 -class TextSymbolizer(Symbolizer):
596 """ 597 A symbolizer for text labels. A TextSymbolizer is a child of a L{Rule} 598 element. 599 600 @prop: Fill 601 602 The element that contains the L{CssParameter} nodes for describing the 603 character fill styles. 604 605 I{Type}: L{Fill} 606 """
607 - def __init__(self, parent, descendant=True):
608 """ 609 Create a new TextSymbolizer node, as a child of the specified parent. 610 611 @type parent: L{Rule} 612 @param parent: The parent class object. 613 @type descendant: boolean 614 @param descendant: A flag indicating if this is a descendant node of the parent. 615 """ 616 super(TextSymbolizer, self).__init__(parent, 'Text*', descendant=descendant)
617
618 619 -class Mark(Symbolizer):
620 """ 621 A graphic mark for describing points. A Mark is a child of a L{Graphic} 622 element. 623 624 @prop: Fill 625 626 The element that contains the L{CssParameter} nodes for describing the 627 fill styles. 628 629 I{Type}: L{Fill} 630 631 @prop: Stroke 632 633 The element that contains the L{CssParameter} nodes for describing the 634 line styles. 635 636 I{Type}: L{Stroke} 637 638 @prop: WellKnownName 639 640 A string describing the Mark, which may be one of: 641 - circle 642 - cross 643 - square 644 - star 645 - triangle 646 - x 647 648 I{Type}: string 649 """
650 - def __init__(self, parent, descendant=True):
651 """ 652 Create a new Mark node, as a child of the specified parent. 653 654 @type parent: L{Graphic} 655 @param parent: The parent class object. 656 @type descendant: boolean 657 @param descendant: A flag indicating if this is a descendant node of the parent. 658 """ 659 super(Mark, self).__init__(parent, 'Mark', descendant=descendant) 660 661 setattr(self.__class__, 'WellKnownName', SLDNode.makeproperty('sld', name='WellKnownName', 662 docstring="The well known name for the mark."))
663
664 665 -class Graphic(SLDNode):
666 """ 667 A Graphic node represents a graphical mark for representing points. A 668 Graphic is a child of a L{PointSymbolizer} element. 669 670 @prop: Mark 671 672 The element that contains the L{CssParameter} nodes for describing the point styles. 673 674 I{Type}: L{Mark} 675 676 @prop: Opacity 677 678 Bewteen 0 (completely transparent) and 1 (completely opaque) 679 680 I{Type}: float 681 682 @prop: Size 683 684 The size of the graphic, in pixels. 685 686 I{Type}: integer 687 688 @prop: Rotation 689 690 Clockwise degrees of rotation. 691 692 I{Type}: float 693 """
694 - def __init__(self, parent, descendant=True):
695 """ 696 Create a new Graphic node, as a child of the specified parent. 697 698 @type parent: L{PointSymbolizer} 699 @param parent: The parent class object. 700 @type descendant: boolean 701 @param descendant: A flag indicating if this is a descendant node of the parent. 702 """ 703 super(Graphic, self).__init__(parent, descendant=descendant) 704 xpath = self._parent.xpath('sld:Graphic', namespaces=SLDNode._nsmap) 705 if len(xpath) < 1: 706 self._node = self._parent.makeelement('{%s}Graphic' % SLDNode._nsmap['sld'], nsmap=SLDNode._nsmap) 707 self._parent.append(self._node) 708 else: 709 self._node = xpath[0] 710 711 setattr(self.__class__, 'Mark', SLDNode.makeproperty('sld', cls=Mark, 712 docstring="The graphic's mark styling.")) 713 setattr(self.__class__, 'Opacity', SLDNode.makeproperty('sld', name='Opacity', 714 docstring="The opacity of the graphic.")) 715 setattr(self.__class__, 'Size', SLDNode.makeproperty('sld', name='Size', 716 docstring="The size of the graphic, in pixels.")) 717 setattr(self.__class__, 'Rotation', SLDNode.makeproperty('sld', name='Rotation', 718 docstring="The rotation of the graphic, in degrees clockwise."))
719
720 721 -class PointSymbolizer(SLDNode):
722 """ 723 A symbolizer for point geometries. A PointSymbolizer is a child of a 724 L{Rule} element. 725 726 @prop: Graphic 727 728 The configuration of the point graphic. 729 730 I{Type}: L{Graphic} 731 """
732 - def __init__(self, parent, descendant=True):
733 """ 734 Create a new PointSymbolizer node, as a child of the specified parent. 735 736 @type parent: L{Rule} 737 @param parent: The parent class object. 738 @type descendant: boolean 739 @param descendant: A flag indicating if this is a descendant node of the parent. 740 """ 741 super(PointSymbolizer, self).__init__(parent, descendant=descendant) 742 xpath = self._parent.xpath('sld:PointSymbolizer', namespaces=SLDNode._nsmap) 743 if len(xpath) < 1: 744 self._node = self._parent.makeelement('{%s}PointSymbolizer' % SLDNode._nsmap['sld'], nsmap=SLDNode._nsmap) 745 self._parent.append(self._node) 746 else: 747 self._node = xpath[0] 748 749 setattr(self.__class__, 'Graphic', SLDNode.makeproperty('sld', cls=Graphic, 750 docstring="The graphic settings for this point geometry."))
751
752 753 -class PropertyCriterion(SLDNode):
754 """ 755 General property criterion class for all property comparitors. 756 A PropertyCriterion is a child of a L{Filter} element. 757 758 Valid property comparitors that are represented by this class are: 759 760 - PropertyIsNotEqual 761 - PropertyIsLessThan 762 - PropertyIsLessThanOrEqual 763 - PropertyIsEqual 764 - PropertyIsGreaterThan 765 - PropertyIsGreaterThanOrEqual 766 - PropertyIsLike 767 768 @prop: PropertyName 769 770 The name of the property to use in the comparison. 771 772 I{Type}: string 773 774 @prop: Literal 775 776 The value of the property. 777 778 I{Type}: string 779 """
780 - def __init__(self, parent, name, descendant=True):
781 """ 782 Create a new PropertyCriterion node, as a child of the specified parent. 783 A PropertyCriterion is not represented in the SLD Spec. This class 784 is a generalization of many of the PropertyIs... elements present in 785 the OGC Filter spec. 786 787 @type parent: L{Filter} 788 @param parent: The parent class object. 789 """ 790 super(PropertyCriterion, self).__init__(parent, descendant=descendant) 791 xpath = self._parent.xpath('ogc:'+name, namespaces=SLDNode._nsmap) 792 if len(xpath) < 1: 793 self._node = self._parent.makeelement('{%s}%s' % (SLDNode._nsmap['ogc'], name), nsmap=SLDNode._nsmap) 794 self._parent.append(self._node) 795 else: 796 self._node = xpath[0] 797 798 setattr(self.__class__, 'PropertyName', SLDNode.makeproperty('ogc', name='PropertyName', 799 docstring="The name of the property to compare.")) 800 setattr(self.__class__, 'Literal', SLDNode.makeproperty('ogc', name='Literal', 801 docstring="The literal value of the property to compare against."))
802
803 804 -class Filter(SLDNode):
805 """ 806 A filter object that stores the property comparitors. A Filter is a child 807 of a L{Rule} element. Filter nodes are pythonic, and have some syntactic 808 sugar that allows the creation of simple logical combinations. 809 810 To create an AND logical filter, use the '+' operator: 811 812 >>> rule.Filter = filter1 + filter2 813 814 To create an OR logical filter, use the '|' operator: 815 816 >>> rule.Filter = filter1 | filter2 817 818 Complex combinations can be created by chaining these operations together: 819 820 >>> rule.Filter = filter1 | (filter2 + filter3) 821 822 @prop: PropertyIsEqualTo 823 824 A specification of property (=) equality. 825 826 I{Type}: L{PropertyCriterion} 827 828 @prop: PropertyIsNotEqualTo 829 830 A specification of property (!=) inequality. 831 832 I{Type}: L{PropertyCriterion} 833 834 @prop: PropertyIsLessThan 835 836 A specification of property less-than (<) comparison. 837 838 I{Type}: L{PropertyCriterion} 839 840 @prop: PropertyIsLessThanOrEqualTo 841 842 A specification of property less-than-or-equal-to (<=) comparison. 843 844 I{Type}: L{PropertyCriterion} 845 846 @prop: PropertyIsGreaterThan 847 848 A specification of property greater-than (>) comparison, 849 850 I{Type}: L{PropertyCriterion} 851 852 @prop: PropertyIsGreaterThanOrEqualTo 853 854 A specification of property greater-than-or-equal-to (>=) comparison. 855 856 I{Type}: L{PropertyCriterion} 857 """
858 - def __init__(self, parent, descendant=True):
859 """ 860 Create a new Filter node. 861 862 @type parent: L{Rule} 863 @param parent: The parent class object. 864 @type descendant: boolean 865 @param descendant: A flag indicating if this is a descendant node of the parent. 866 """ 867 super(Filter, self).__init__(parent, descendant=descendant) 868 xpath = self._parent.xpath('ogc:Filter', namespaces=SLDNode._nsmap) 869 if len(xpath) == 1: 870 self._node = xpath[0] 871 else: 872 self._node = self._parent.makeelement('{%s}Filter' % SLDNode._nsmap['ogc'], nsmap=SLDNode._nsmap)
873 874
875 - def __add__(self, other):
876 """ 877 Add two filters together to create one AND logical filter. 878 879 @type other: L{Filter} 880 @param other: A filter to AND with this one. 881 @rtype: L{Filter} 882 @return: A new filter with an ogc:And element as its child. 883 """ 884 if not self._node.getparent() is None: 885 self._node.getparent().remove(self._node) 886 elem = self._node.makeelement('{%s}And' % SLDNode._nsmap['ogc']) 887 elem.append(copy.copy(self._node[0])) 888 elem.append(copy.copy(other._node[0])) 889 890 f = Filter(self) 891 f._node.append(elem) 892 893 return f
894
895 - def __or__(self, other):
896 """ 897 Or two filters together to create on OR logical filter. 898 899 @type other: L{Filter} 900 @param other: A filter to OR with this one. 901 @rtype: L{Filter} 902 @return: A new filter with an ogc:Or element as its child. 903 """ 904 elem = self._node.makeelement('{%s}Or' % SLDNode._nsmap['ogc']) 905 elem.append(copy.copy(self._node[0])) 906 elem.append(copy.copy(other._node[0])) 907 908 f = Filter(self) 909 f._node.append(elem) 910 911 return f
912
913 - def __getattr__(self, name):
914 """ 915 Get a named attribute from this Filter instance. This method allows 916 properties with the prefix of 'PropertyIs' to be set, and raises 917 an AttributeError for all other property names. 918 919 @type name: string 920 @param name: The name of the property. 921 @rtype: L{PropertyCriterion} 922 @return: The property comparitor. 923 """ 924 if not name.startswith('PropertyIs'): 925 raise AttributeError('Property name must be one of: PropertyIsEqualTo, PropertyIsNotEqualTo, PropertyIsLessThan, PropertyIsLessThanOrEqualTo, PropertyIsGreaterThan, PropertyIsGreaterThanOrEqualTo, PropertyIsLike.') 926 xpath = self._node.xpath('ogc:'+name, namespaces=SLDNode._nsmap) 927 if len(xpath) == 0: 928 return None 929 930 return PropertyCriterion(self, name)
931
932 - def __setattr__(self, name, value):
933 """ 934 Set a named attribute on this Filter instance. If the property name 935 begins with 'PropertyIs', the node value will be appended to the filter. 936 937 @type name: string 938 @param name: The name of the property. 939 @type value: L{PropertyCriterion} 940 @param value: The new property comparitor. 941 """ 942 if not name.startswith('PropertyIs'): 943 object.__setattr__(self, name, value) 944 return 945 946 xpath = self._node.xpath('ogc:'+name, namespaces=SLDNode._nsmap) 947 if len(xpath) > 0: 948 xpath[0] = value 949 else: 950 elem = self._node.makeelement('{%s}%s' % (SLDNode._nsmap['ogc'], name), nsmap=SLDNode._nsmap) 951 self._node.append(elem)
952
953 - def __delattr__(self, name):
954 """ 955 Delete the property from the Filter. This removes the child node 956 of this name from the Filter. 957 958 @type name: string 959 @param name: The name of the property. 960 """ 961 xpath = self._node.xpath('ogc:'+name, namespaces=SLDNode._nsmap) 962 if len(xpath) > 0: 963 self._node.remove(xpath[0])
964
965 966 -class Rule(SLDNode):
967 """ 968 A rule object contains a title, an optional L{Filter}, and one or more 969 L{Symbolizer}s. A Rule is a child of a L{FeatureTypeStyle}. 970 971 @prop: Title 972 973 The title of this rule. This is required for a valid SLD. 974 975 I{Type}: string 976 977 @prop: Filter 978 979 Optional. A filter defines logical comparisons against properties. 980 981 I{Type}: L{Filter} 982 983 @prop: PolygonSymbolizer 984 985 A symbolizer that defines how polygons should be rendered. 986 987 I{Type}: L{PolygonSymbolizer} 988 989 @prop: LineSymbolizer 990 991 A symbolizer that defines how lines should be rendered. 992 993 I{Type}: L{LineSymbolizer} 994 995 @prop: TextSymbolizer 996 997 A symbolizer that defines how text should be rendered. 998 999 I{Type}: L{TextSymbolizer} 1000 1001 @prop: PointSymbolizer 1002 1003 A symbolizer that defines how points should be rendered. 1004 1005 I{Type}: L{PointSymbolizer} 1006 """
1007 - def __init__(self, parent, index, descendant=True):
1008 """ 1009 Create a new Rule node. 1010 1011 @type parent: L{FeatureTypeStyle} 1012 @param parent: The parent class object. 1013 @type descendant: boolean 1014 @param descendant: A flag indicating if this is a descendant node of the parent. 1015 """ 1016 super(Rule, self).__init__(parent, descendant=descendant) 1017 self._node = self._parent.xpath('sld:Rule', namespaces=SLDNode._nsmap)[index] 1018 1019 setattr(self.__class__, 'Title', SLDNode.makeproperty('sld', name='Title', 1020 docstring="The title of the Rule.")) 1021 setattr(self.__class__, 'Filter', SLDNode.makeproperty('ogc', cls=Filter, 1022 docstring="The optional filter object, with property comparitors.")) 1023 setattr(self.__class__, 'PolygonSymbolizer', SLDNode.makeproperty('sld', cls=PolygonSymbolizer, 1024 docstring="The optional polygon symbolizer for this rule.")) 1025 setattr(self.__class__, 'LineSymbolizer', SLDNode.makeproperty('sld', cls=LineSymbolizer, 1026 docstring="The optional line symbolizer for this rule.")) 1027 setattr(self.__class__, 'TextSymbolizer', SLDNode.makeproperty('sld', cls=TextSymbolizer, 1028 docstring="The optional text symbolizer for this rule.")) 1029 setattr(self.__class__, 'PointSymbolizer', SLDNode.makeproperty('sld', cls=PointSymbolizer, 1030 docstring="The optional point symbolizer for this rule."))
1031
1032 - def normalize(self):
1033 """ 1034 Normalize this node prior to validation. This is required, as the 1035 ogc:Filter node must come before any symbolizer nodes. The SLD 1036 is modified in place. 1037 """ 1038 order = ['sld:Title','ogc:Filter','sld:PolygonSymbolizer', 1039 'sld:LineSymbolizer', 'sld:TextSymbolizer', 'sld:PointSymbolizer'] 1040 for item in order: 1041 xpath = self._node.xpath(item, namespaces=SLDNode._nsmap) 1042 for xitem in xpath: 1043 # move this to the end 1044 self._node.remove(xitem) 1045 self._node.append(xitem)
1046 1047 # no need to normalize children 1048
1049 - def create_filter(self, propname=None, comparitor=None, value=None):
1050 """ 1051 Create a L{Filter} for this rule. The property name, comparitor, and value 1052 are required to create a valid Filter. 1053 1054 @type propname: string 1055 @param propname: The name of the property to filter. 1056 @type comparitor: string 1057 @param comparitor: The comparison to perform on the property. One of 1058 "!=", "<", "<=", "=", ">=", ">", and "%" is required. 1059 @type value: string 1060 @param value: The value of the property to compare against. 1061 @rtype: L{Filter} 1062 @return: A new filter attached to this Rule. 1063 """ 1064 if propname is None or comparitor is None or value is None: 1065 return None 1066 1067 rfilter = self.create_element('ogc', 'Filter') 1068 ftype = None 1069 if comparitor == '==': 1070 ftype = 'PropertyIsEqualTo' 1071 elif comparitor == '<=': 1072 ftype = 'PropertyIsLessThanOrEqualTo' 1073 elif comparitor == '<': 1074 ftype = 'PropertyIsLessThan' 1075 elif comparitor == '>=': 1076 ftype = 'PropertyIsGreaterThanOrEqualTo' 1077 elif comparitor == '>': 1078 ftype = 'PropertyIsGreaterThan' 1079 elif comparitor == '!=': 1080 ftype = 'PropertyIsNotEqualTo' 1081 elif comparitor == '%': 1082 ftype = 'PropertyIsLike' 1083 1084 if not ftype is None: 1085 prop = PropertyCriterion(rfilter, ftype) 1086 prop.PropertyName = propname 1087 if not value is None: 1088 prop.Literal = value 1089 setattr(rfilter, ftype, prop) 1090 1091 return rfilter
1092
1093 - def create_symbolizer(self, stype):
1094 """ 1095 Create a L{Symbolizer} of the specified type on this rule. 1096 1097 @type stype: string 1098 @param stype: The type of symbolizer. Allowed types are "Point", 1099 "Line", "Polygon", or "Text". 1100 @rtype: L{Symbolizer} 1101 @return: A newly created symbolizer, attached to this Rule. 1102 """ 1103 if stype is None: 1104 return None 1105 1106 return self.create_element('sld', stype + 'Symbolizer')
1107
1108 1109 -class Rules(SLDNode):
1110 """ 1111 A collection of L{Rule} nodes. This is a pythonic helper (list of 1112 nodes) that does not correspond to a true element in the SLD spec. 1113 """
1114 - def __init__(self, parent, descendant=True):
1115 """ 1116 Create a new list of Rules from the specified parent node. 1117 1118 @type parent: L{FeatureTypeStyle} 1119 @param parent: The parent class object. 1120 @type descendant: boolean 1121 @param descendant: A flag indicating if this is a descendant node of the parent. 1122 """ 1123 super(Rules, self).__init__(parent, descendant=descendant) 1124 self._node = None 1125 self._nodes = self._parent.xpath('sld:Rule', namespaces=SLDNode._nsmap)
1126
1127 - def normalize(self):
1128 """ 1129 Normalize this node and all rules contained within. The SLD model is 1130 modified in place. 1131 """ 1132 for i,rnode in enumerate(self._nodes): 1133 rule = Rule(self, i-1, descendant=False) 1134 rule.normalize()
1135
1136 - def __len__(self):
1137 """ 1138 Get the number of L{CssParameter} nodes in this list. 1139 1140 @rtype: integer 1141 @return: The number of L{CssParameter} nodes. 1142 """ 1143 return len(self._nodes)
1144
1145 - def __getitem__(self, key):
1146 """ 1147 Get one of the L{Rule} nodes in the list. 1148 1149 @type key: integer 1150 @param key: The index of the child node. 1151 @rtype: L{Rule} 1152 @return: The specific L{Rule} node. 1153 """ 1154 rule = Rule(self, key, descendant=False) 1155 return rule
1156
1157 - def __setitem__(self, key, value):
1158 """ 1159 Set one of the L{Rule} nodes in the list with a new value. 1160 1161 @type key: integer 1162 @param key: The index of the child node. 1163 @type value: L{Rule}, etree.Element 1164 @param value: The new value of the specific child node. 1165 """ 1166 if isinstance(value, Rule): 1167 self._nodes.replace(self._nodes[key], value._node) 1168 elif isinstance(value, Element): 1169 self._nodes.replace(self._nodes[key], value)
1170
1171 - def __delitem__(self, key):
1172 """ 1173 Delete one of the L{Rule} nodes from the list. 1174 1175 @type key: integer 1176 @param key: The index of the child node. 1177 """ 1178 self._nodes.remove(self._nodes[key])
1179
1180 1181 -class FeatureTypeStyle(SLDNode):
1182 """ 1183 A FeatureTypeStyle node contains all L{Rule} objects applicable to a 1184 specific layer. A FeatureTypeStyle is a child of a L{UserStyle} element. 1185 """
1186 - def __init__(self, parent, descendant=True):
1187 """ 1188 Create a new FeatureTypeNode node, as a child of the specified parent. 1189 1190 @type parent: L{UserStyle} 1191 @param parent: The parent class object. 1192 @type descendant: boolean 1193 @param descendant: A flag indicating if this is a descendant node of the parent. 1194 """ 1195 super(FeatureTypeStyle, self).__init__(parent, descendant=descendant) 1196 self._node = self._parent.xpath('sld:FeatureTypeStyle', namespaces=SLDNode._nsmap)[0]
1197
1198 - def normalize(self):
1199 """ 1200 Normalize this element and all child L{Rule}s. The SLD model is 1201 modified in place. 1202 """ 1203 if not self.Rules is None: 1204 self.Rules.normalize()
1205 1206 @property
1207 - def Rules(self):
1208 """ 1209 Get the L{sld.Rules} pythonic list helper for all L{Rule} objects in this 1210 style. 1211 1212 @rtype: L{sld.Rules} 1213 @return: A list of all rules applied to this style. 1214 """ 1215 return Rules(self)
1216
1217 - def create_rule(self, title, symbolizer=None):
1218 """ 1219 Create a L{Rule} object on this style. A rule requires a title and 1220 symbolizer. If no symbolizer is specified, a PointSymbolizer will be 1221 assigned to the rule. 1222 1223 @type title: string 1224 @param title: The name of the new L{Rule}. 1225 @type symbolizer: L{Symbolizer} I{class} 1226 @param symbolizer: The symbolizer type. This is the class object (as 1227 opposed to a class instance) of the symbolizer to use. 1228 @rtype: L{Rule} 1229 @return: A newly created rule, attached to this FeatureTypeStyle. 1230 """ 1231 elem = self._node.makeelement('{%s}Rule' % SLDNode._nsmap['sld'], nsmap=SLDNode._nsmap) 1232 self._node.append(elem) 1233 1234 rule = Rule(self, len(self._node)-1) 1235 rule.Title = title 1236 1237 if symbolizer is None: 1238 symbolizer = PointSymbolizer 1239 1240 sym = symbolizer(rule) 1241 if symbolizer == PointSymbolizer: 1242 gph = Graphic(sym) 1243 mrk = Mark(gph) 1244 mrk.WellKnownName = 'square' 1245 fill = Fill(mrk) 1246 fill.create_cssparameter('fill', '#ff0000') 1247 1248 elif symbolizer == LineSymbolizer: 1249 stroke = Stroke(sym) 1250 stroke.create_cssparameter('stroke', '#0000ff') 1251 1252 elif symbolizer == PolygonSymbolizer: 1253 fill = Fill(sym) 1254 fill.create_cssparameter('fill', '#AAAAAA') 1255 stroke = Stroke(sym) 1256 stroke.create_cssparameter('stroke', '#000000') 1257 stroke.create_cssparameter('stroke-width', '1') 1258 1259 return rule
1260
1261 1262 -class UserStyle(SLDNode):
1263 """ 1264 A UserStyle object. A UserStyle is a child of a L{StyledLayerDescriptor}. 1265 1266 @prop: Title 1267 1268 The title of the UserStyle. 1269 1270 I{Type}: string 1271 1272 @prop: Abstract 1273 1274 The abstract describing this UserStyle. 1275 1276 I{Type}: string 1277 1278 @prop: FeatureTypeStyle 1279 1280 The styling for the feature type. 1281 1282 I{Type}: L{FeatureTypeStyle} 1283 """
1284 - def __init__(self, parent, descendant=True):
1285 """ 1286 Create a new UserStyle node. 1287 1288 @type parent: L{NamedLayer} 1289 @param parent: The parent class object. 1290 @type descendant: boolean 1291 @param descendant: A flag indicating if this is a descendant node of the parent. 1292 """ 1293 super(UserStyle, self).__init__(parent, descendant=descendant) 1294 self._node = self._parent.xpath('sld:UserStyle', namespaces=SLDNode._nsmap)[0] 1295 1296 setattr(self.__class__, 'Title', SLDNode.makeproperty('sld', name='Title', 1297 docstring="The title of the UserStyle.")) 1298 setattr(self.__class__, 'Abstract', SLDNode.makeproperty('sld', name='Abstract', 1299 docstring="The abstract of the UserStyle.")) 1300 setattr(self.__class__, 'FeatureTypeStyle', SLDNode.makeproperty('sld', cls=FeatureTypeStyle, 1301 docstring="The feature type style of the UserStyle."))
1302
1303 - def normalize(self):
1304 """ 1305 Normalize this node and all child nodes prior to validation. The SLD 1306 is modified in place. 1307 """ 1308 if not self.FeatureTypeStyle is None: 1309 self.FeatureTypeStyle.normalize()
1310
1311 - def create_featuretypestyle(self):
1312 """ 1313 Create a L{FeatureTypeStyle} object, and attach it to this UserStyle. 1314 1315 @rtype: L{FeatureTypeStyle} 1316 @return: A newly created feature type style, attached to this node. 1317 """ 1318 return self.get_or_create_element('sld', 'FeatureTypeStyle')
1319
1320 1321 -class NamedLayer(SLDNode):
1322 """ 1323 A named layer contains a name and a user style. A NamedLayer is a child of 1324 a L{StyledLayerDescriptor}. 1325 1326 @prop: Name 1327 1328 The name of the UserStyle. 1329 1330 I{Type}: string 1331 1332 @prop: UserStyle 1333 1334 The custom styling for this named layer. 1335 1336 I{Type}: L{UserStyle} 1337 """
1338 - def __init__(self, parent, descendant=True):
1339 """ 1340 Create a new NamedLayer node. 1341 1342 @type parent: L{StyledLayerDescriptor} 1343 @param parent: The parent class object. 1344 @type descendant: boolean 1345 @param descendant: A flag indicating if this is a descendant node of the parent. 1346 """ 1347 super(NamedLayer, self).__init__(parent, descendant=descendant) 1348 self._node = self._parent.xpath('sld:NamedLayer', namespaces=SLDNode._nsmap)[0] 1349 1350 setattr(self.__class__, 'UserStyle', SLDNode.makeproperty('sld', cls=UserStyle, 1351 docstring="The UserStyle of the NamedLayer.")) 1352 setattr(self.__class__, 'Name', SLDNode.makeproperty('sld', name='Name', 1353 docstring="The name of the layer."))
1354
1355 - def normalize(self):
1356 """ 1357 Normalize this node and all child nodes prior to validation. The SLD 1358 is modified in place. 1359 """ 1360 if not self.UserStyle is None: 1361 self.UserStyle.normalize()
1362
1363 - def create_userstyle(self):
1364 """ 1365 Create a L{UserStyle} for this named layer. 1366 1367 @rtype: L{UserStyle} 1368 @return: A newly created user style, attached to this node. 1369 """ 1370 return self.get_or_create_element('sld', 'UserStyle')
1371
1372 1373 -class StyledLayerDescriptor(SLDNode):
1374 """ 1375 An object representation of an SLD document. 1376 1377 @prop: NamedLayer 1378 1379 The named layer that this styling applies to. 1380 1381 I{Type}: L{NamedLayer} 1382 """ 1383 1384 _cached_schema = None 1385 """A cached schema document, to prevent multiple requests from occurring.""" 1386
1387 - def __init__(self, sld_file=None):
1388 """ 1389 Create a new SLD document. If an sld file is provided, this constructor 1390 will fetch the SLD schema from the internet and validate the file 1391 against that schema. 1392 1393 @type sld_file: string 1394 @param sld_file: The name of a pre-existing SLD file. 1395 """ 1396 super(StyledLayerDescriptor, self).__init__(None) 1397 1398 if StyledLayerDescriptor._cached_schema is None: 1399 logging.debug('Storing new schema into cache.') 1400 1401 localschema = NamedTemporaryFile(delete=False) 1402 schema_url = 'http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd' 1403 resp = urllib2.urlopen(schema_url) 1404 localschema.write(resp.read()) 1405 resp.close() 1406 localschema.seek(0) 1407 1408 theschema = parse(localschema) 1409 localschema.close() 1410 1411 StyledLayerDescriptor._cached_schema = localschema.name 1412 else: 1413 logging.debug('Fetching schema from cache.') 1414 1415 localschema = open(StyledLayerDescriptor._cached_schema, 'r') 1416 theschema = parse(localschema) 1417 localschema.close() 1418 1419 self._schema = XMLSchema(theschema) 1420 1421 if not sld_file is None: 1422 self._node = parse(sld_file) 1423 1424 if not self._schema.validate(self._node): 1425 logging.warn('SLD File "%s" does not validate against the SLD schema.', sld_file) 1426 else: 1427 self._node = Element("{%s}StyledLayerDescriptor" % SLDNode._nsmap['sld'], version="1.0.0", nsmap=SLDNode._nsmap) 1428 1429 setattr(self.__class__, 'NamedLayer', SLDNode.makeproperty('sld', cls=NamedLayer, 1430 docstring="The named layer of the SLD."))
1431
1432 - def __del__(self):
1433 """ 1434 Destroy the StyledLayerDescriptor object, and clear its cache. 1435 """ 1436 if not StyledLayerDescriptor._cached_schema is None: 1437 logging.debug('Clearing cached schema.') 1438 1439 os.remove(StyledLayerDescriptor._cached_schema) 1440 StyledLayerDescriptor._cached_schema = None
1441
1442 - def __deepcopy__(self, memo):
1443 """ 1444 Perform a deep copy. Instead of copying references to the schema 1445 object, create a new SLD, and deepcopy the SLD node. 1446 """ 1447 sld = StyledLayerDescriptor() 1448 sld._node = copy.deepcopy(self._node) 1449 return sld
1450 1451
1452 - def normalize(self):
1453 """ 1454 Normalize this node and all child nodes prior to validation. The SLD 1455 is modified in place. 1456 """ 1457 if not self.NamedLayer is None: 1458 self.NamedLayer.normalize()
1459 1460
1461 - def validate(self):
1462 """ 1463 Validate the current file against the SLD schema. This first normalizes 1464 the SLD document, then validates it. Any schema validation error messages 1465 are logged at the INFO level. 1466 1467 @rtype: boolean 1468 @return: A flag indicating if the SLD is valid. 1469 """ 1470 self.normalize() 1471 1472 if self._node is None or self._schema is None: 1473 logging.debug('The node or schema is empty, and cannot be validated.') 1474 return False 1475 1476 is_valid = self._schema.validate(self._node) 1477 1478 for msg in self._schema.error_log: 1479 logging.info('Line:%d, Column:%d -- %s', msg.line, msg.column, msg.message) 1480 1481 return is_valid
1482 1483 1484 @property
1485 - def version(self):
1486 """ 1487 Get the SLD version. 1488 """ 1489 return self._node.getroot().get('version')
1490 1491 @property
1492 - def xmlns(self):
1493 """ 1494 Get the XML Namespace. 1495 """ 1496 return self._node.getroot().nsmap[None]
1497
1498 - def create_namedlayer(self, name):
1499 """ 1500 Create a L{NamedLayer} in this SLD. 1501 1502 @type name: string 1503 @param name: The name of the layer. 1504 @rtype: L{NamedLayer} 1505 @return: The named layer, attached to this SLD. 1506 """ 1507 namedlayer = self.get_or_create_element('sld', 'NamedLayer') 1508 namedlayer.Name = name 1509 return namedlayer
1510
1511 - def as_sld(self, pretty_print=False):
1512 """ 1513 Serialize this SLD model into a string. 1514 1515 @rtype: string 1516 @returns: The content of the SLD. 1517 """ 1518 return tostring(self._node, pretty_print=pretty_print)
1519