1 |
bh |
75 |
# Copyright (C) 2001, 2002 by Intevation GmbH |
2 |
bh |
6 |
# Authors: |
3 |
|
|
# Jan-Oliver Wagner <[email protected]> |
4 |
|
|
# |
5 |
|
|
# This program is free software under the GPL (>=v2) |
6 |
|
|
# Read the file COPYING coming with GRASS for details. |
7 |
|
|
|
8 |
|
|
""" |
9 |
|
|
Parser for thuban session files. |
10 |
|
|
""" |
11 |
|
|
|
12 |
|
|
__version__ = "$Revision$" |
13 |
|
|
|
14 |
|
|
import sys, string, os |
15 |
|
|
from Thuban.Model.session import Session |
16 |
|
|
from Thuban.Model.map import Map |
17 |
|
|
from Thuban.Model.layer import Layer |
18 |
|
|
from Thuban.Model.color import Color |
19 |
|
|
from Thuban.Model.proj import Projection |
20 |
|
|
|
21 |
|
|
oldPython=0 |
22 |
|
|
|
23 |
|
|
if not sys.__dict__.has_key("version_info"): |
24 |
|
|
# We can assume to have python 1.5.2 or lower here now |
25 |
|
|
oldPython=1 |
26 |
|
|
|
27 |
|
|
if oldPython: |
28 |
|
|
try: |
29 |
|
|
from xml.sax.saxexts import make_parser |
30 |
|
|
from xml.sax.saxlib import HandlerBase |
31 |
|
|
from xml.sax import saxutils |
32 |
|
|
except ImportError: |
33 |
|
|
sys.stdout.write(("You need to have Python-XML installed or" |
34 |
|
|
" a modern Python!\n" |
35 |
|
|
"Check www.python.org/sigs/xml-sig/\n\n")) |
36 |
|
|
raise |
37 |
|
|
else: |
38 |
|
|
# Do the python 2.0 standard xml thing and map it on the old names |
39 |
|
|
import xml.sax |
40 |
|
|
import xml.sax.handler |
41 |
|
|
HandlerBase=xml.sax.handler.ContentHandler |
42 |
|
|
from xml.sax import make_parser |
43 |
|
|
|
44 |
|
|
class testSAXContentHandler(HandlerBase): |
45 |
|
|
# SAX compliant |
46 |
|
|
def characters(self, ch, start, length): |
47 |
|
|
pass |
48 |
|
|
|
49 |
|
|
def test_for_broken_SAX(): |
50 |
|
|
ch=testSAXContentHandler() |
51 |
|
|
try: |
52 |
|
|
xml.sax.parseString("""<?xml version="1.0"?> |
53 |
|
|
<child1 name="paul">Text goes here</child1> |
54 |
|
|
""",ch) |
55 |
|
|
except TypeError: |
56 |
|
|
return 1 |
57 |
|
|
return 0 |
58 |
|
|
|
59 |
|
|
|
60 |
|
|
def parse_color(color): |
61 |
|
|
""" |
62 |
|
|
Return the color object for the string color. Color may be either |
63 |
|
|
'None' or of the form '#RRGGBB' in the usual HTML color notation |
64 |
|
|
""" |
65 |
|
|
color = string.strip(color) |
66 |
|
|
if color == "None": |
67 |
|
|
result = None |
68 |
|
|
elif color[0] == '#': |
69 |
|
|
if len(color) == 7: |
70 |
|
|
r = string.atoi(color[1:3], 16) / 255.0 |
71 |
|
|
g = string.atoi(color[3:5], 16) / 255.0 |
72 |
|
|
b = string.atoi(color[5:7], 16) / 255.0 |
73 |
|
|
result = Color(r, g, b) |
74 |
|
|
else: |
75 |
|
|
raise ValueError("Invalid hexadecimal color specification %s" |
76 |
|
|
% color) |
77 |
|
|
else: |
78 |
|
|
raise ValueError("Invalid color specification %s" % color) |
79 |
|
|
return result |
80 |
|
|
|
81 |
|
|
|
82 |
|
|
class ProcessSession(HandlerBase): |
83 |
|
|
|
84 |
|
|
def __init__(self, directory): |
85 |
|
|
"""Inititialize the Sax handler. |
86 |
|
|
|
87 |
|
|
directory is the directory containing the session file. It's |
88 |
|
|
needed to interpret embedded relative filenames |
89 |
|
|
""" |
90 |
|
|
self.directory = directory |
91 |
|
|
self.chars = '' |
92 |
|
|
self.theSession = None |
93 |
|
|
self.aMap = None |
94 |
|
|
self.aLayer = None |
95 |
|
|
|
96 |
|
|
def startElement(self, name, attrs): |
97 |
|
|
if name == 'session': |
98 |
|
|
self.theSession = Session(attrs.get('title', None)) |
99 |
|
|
elif name == 'map': |
100 |
|
|
self.aMap = Map(attrs.get('title', None)) |
101 |
|
|
elif name == 'projection': |
102 |
|
|
self.ProjectionParams = [ ] |
103 |
|
|
elif name == 'parameter': |
104 |
|
|
self.ProjectionParams.append(attrs.get('value', None)) |
105 |
|
|
elif name == 'layer': |
106 |
|
|
title = attrs.get('title', "") |
107 |
|
|
filename = attrs.get('filename', "") |
108 |
|
|
filename = os.path.join(self.directory, filename) |
109 |
|
|
fill = parse_color(attrs.get('fill', "None")) |
110 |
bh |
75 |
stroke = parse_color(attrs.get('stroke', "#000000")) |
111 |
|
|
stroke_width = int(attrs.get("stroke_width", "1")) |
112 |
|
|
self.aLayer = Layer(title, filename, fill = fill, stroke = stroke, |
113 |
|
|
stroke_width = stroke_width) |
114 |
bh |
6 |
elif name == 'table': |
115 |
|
|
print "table title: %s" % attrs.get('title', None) |
116 |
|
|
elif name == 'labellayer': |
117 |
|
|
self.aLayer = self.aMap.LabelLayer() |
118 |
|
|
elif name == 'label': |
119 |
|
|
x = float(attrs['x']) |
120 |
|
|
y = float(attrs['y']) |
121 |
|
|
text = attrs['text'] |
122 |
|
|
halign = attrs['halign'] |
123 |
|
|
valign = attrs['valign'] |
124 |
|
|
self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign) |
125 |
|
|
|
126 |
|
|
|
127 |
|
|
if not oldPython and test_for_broken_SAX(): |
128 |
|
|
# works with python 2.0, but is not SAX compliant |
129 |
|
|
def characters(self, ch): |
130 |
|
|
self.my_characters(ch) |
131 |
|
|
else: |
132 |
|
|
# SAX compliant |
133 |
|
|
def characters(self, ch, start, length): |
134 |
|
|
self.my_characters(ch[start:start+length]) |
135 |
|
|
|
136 |
|
|
def my_characters(self, ch): |
137 |
|
|
self.chars = self.chars + ch |
138 |
|
|
|
139 |
|
|
def endElement(self, name): |
140 |
|
|
# If it's not a parameter element, ignore it |
141 |
|
|
if name == 'session': |
142 |
|
|
#print "end of session" |
143 |
|
|
pass |
144 |
|
|
if name == 'map': |
145 |
|
|
self.theSession.AddMap(self.aMap) |
146 |
|
|
if name == 'projection': |
147 |
|
|
self.aMap.SetProjection(Projection(self.ProjectionParams)) |
148 |
|
|
if name == 'layer': |
149 |
|
|
self.aMap.AddLayer(self.aLayer) |
150 |
|
|
if name == 'table': |
151 |
|
|
#print "end of table" |
152 |
|
|
pass |
153 |
|
|
|
154 |
|
|
def load_session(filename): |
155 |
|
|
"""Load a Thuban session from the file object file""" |
156 |
|
|
dir = os.path.dirname(filename) |
157 |
|
|
file = open(filename) |
158 |
|
|
handler = ProcessSession(dir) |
159 |
|
|
|
160 |
|
|
if oldPython: |
161 |
|
|
parser = make_parser() |
162 |
|
|
parser.setDocumentHandler(handler) |
163 |
|
|
parser.setErrorHandler(saxutils.ErrorPrinter()) |
164 |
|
|
parser.parseFile(file) |
165 |
|
|
parser.close() |
166 |
|
|
else: |
167 |
|
|
xml.sax.parse(file,handler) |
168 |
|
|
session = handler.theSession |
169 |
|
|
# Newly loaded session aren't modified |
170 |
|
|
session.UnsetModified() |
171 |
|
|
|
172 |
|
|
return session |
173 |
|
|
|
174 |
|
|
if __name__ == "__main__": |
175 |
|
|
# find out the command to run |
176 |
|
|
if len(sys.argv) > 1: |
177 |
|
|
print "usage: cat <file> | " + sys.argv[0] |
178 |
|
|
else: |
179 |
|
|
parseSession(sys.stdin) |