source: subversion/applications/utils/export/segmentise/Parser.cpp @ 28183

Last change on this file since 28183 was 24427, checked in by nick, 9 years ago

Fixed xml entities quot, apos, amp. Need to find more general way of dealing with all entities - TODO

File size: 6.2 KB
Line 
1#include "Parser.h"
2#include <string>
3#include <cstring>
4#include <sstream>
5
6
7
8int Parser::curID = 0;
9bool Parser::inNode = false, Parser::inWay = false;
10std::string Parser::error = "";
11int Parser::wayCount = 1;
12bool Parser::initialRun = true;
13std::map<int,Node*>  Parser::nodes;
14Way Parser::curWay;
15
16std::string Parser::getError()
17{
18    return error;
19}
20
21void Parser::startElement(void *d, const XML_Char* element,
22        const XML_Char** attrs)
23{
24    double lat, lon;
25    int count=0;
26
27
28    if(!strcmp(element,"osm"))
29    {
30        if(!initialRun)
31            cout<<"<osm>"<<endl;
32    }
33    if (!strcmp(element, "node"))
34    {
35        curID = 0;
36        inNode = true;
37        while (attrs[count])
38        {
39            if (!strcmp(attrs[count], "lat"))
40                lat = atof(attrs[count + 1]);
41            if (!strcmp(attrs[count], "lon"))
42                lon = atof(attrs[count + 1]);
43            if (!strcmp(attrs[count], "id"))
44                curID = atoi(attrs[count + 1]);
45            count += 2;
46        }
47        // store the node if first run
48        if(initialRun)
49        {
50            nodes[curID] = new Node(lat,lon); 
51            ///cerr<<"Storing node: "<<curID<<endl;
52        }
53        // write the node straight out if second run
54        else   
55        {   
56                        cout.precision(8);
57            cout << "<node id=\""<<curID<<"\" lat=\""<<lat<<"\" lon=\""
58                    <<lon<<"\">" << endl;
59        }
60    }
61    else if (!strcmp(element, "way"))
62    {
63        inWay = true;
64
65        // do nothing on first run
66        if(!initialRun)
67        {   
68            curWay.tags.clear();
69            curWay.nds.clear();
70
71            while (attrs[count])
72            {
73                if (!strcmp(attrs[count], "id"))
74                    curWay.tags["osm_id"] = attrs[count+1];
75                count += 2;
76            }
77        }
78    }
79    else if (!strcmp(element, "nd") && (inWay))
80    {
81        int ndID;
82
83        for (int count = 0; attrs[count]; count += 2)
84        {
85            if (!strcmp(attrs[count], "ref"))
86            {
87                ndID = atoi(attrs[count + 1]);
88
89                // Increase the count for this node if initial run
90                if(initialRun && nodes[ndID])
91                {
92                    nodes[ndID]->count++;
93                    /*
94                    cerr<<"Increasing count of node: "<<ndID<<
95                        " count now " <<nodes[ndID]->count<<endl;
96                    */
97                }
98                else
99                {
100                    curWay.nds.push_back(ndID);
101                }
102            }
103        }
104    }
105    else if (!strcmp(element, "tag"))
106    {
107
108        // write out tags (for node and way) in second run
109        if(!initialRun)
110        {
111                std::string key = "", value = "";
112
113                for (int count = 0; attrs[count]; count += 2)
114                {
115                if (!strcmp(attrs[count], "k"))
116                        key = attrs[count + 1];
117                if (!strcmp(attrs[count], "v"))
118                        value = attrs[count + 1];
119
120                }
121
122                        int idx=value.find("&");
123                        while(idx>=0)
124                        {
125                                value=value.replace(idx,1,"&amp;");
126                                idx=value.find("&",idx+1);
127                        }
128                        idx=value.find("\"");
129                        while(idx>=0)
130                        {
131                                value=value.replace(idx,1,"&quot;");
132                                idx=value.find("\"",idx);
133                        }
134                        idx=value.find("'");
135                        while(idx>=0)
136                        {
137                                value=value.replace(idx,1,"&apos;");
138                                idx=value.find("'");
139                        }
140
141            if(inNode)
142                cout<<"<tag k=\""<<key<<"\" v=\""<<value<<"\" />"<<endl;
143            else if (inWay) // save as might be applied multiple times
144            {
145                curWay.tags[key] = value;
146            }
147        }
148    }
149}
150
151void Parser::endElement(void *d, const XML_Char* element)
152{
153    if (!strcmp(element, "node"))
154    {
155        inNode = false;
156        if(!initialRun)
157            cout << "</node>\n";
158    }
159    else if (!strcmp(element, "way"))
160    {
161        inWay = false;
162        if(!initialRun)
163        {
164            cout << "<way id=\""<<wayCount++<<"\">\n";
165            for(int i=0; i<curWay.nds.size(); i++)
166            {
167                cout<<"<nd ref=\""<<curWay.nds[i]<<"\" />" << endl;
168
169                // split the way if it\"s a node in more than 1 way and not
170                // the end nodes
171                if(i && i!=curWay.nds.size()-1 &&
172                    nodes[curWay.nds[i]] && nodes[curWay.nds[i]]->count >= 2)
173                {
174                    writeCurrentTags(curWay.tags);//write the tags for the way
175                    cout << "</way>\n";
176                    cout << "<way id=\""<<wayCount++<<"\">\n";
177                    cout<<"<nd ref=\""<<curWay.nds[i]<<"\" />" << endl;
178                }
179            }
180            writeCurrentTags(curWay.tags);
181            cout << "</way>" << endl;
182        }
183    }
184    else if (!strcmp(element,"osm"))
185    {
186        if(initialRun)
187            initialRun=false;
188        else
189        {
190            cout<<"</osm>"<<endl;
191            freeNodes();
192        }
193    }
194}
195
196void Parser::characters(void*, const XML_Char* txt, int txtlen)
197{
198}
199
200void Parser::writeCurrentTags(std::map<std::string,std::string>& tags)
201{
202    std::map<std::string,std::string>::iterator i=tags.begin();
203    while(i != tags.end())
204    {
205        cout<<"<tag k=\"" << i->first << "\" v=\""<<i->second<<"\" />"<<endl;
206        i++;
207    }
208}
209
210void Parser::freeNodes()
211{
212    for(std::map<int,Node*>::iterator i=nodes.begin(); i!=nodes.end(); i++)
213        delete i->second;
214}
215
216
217bool Parser::parse(XML_Parser p,std::istream &in)
218{
219    int done, count = 0, n;
220    char buf[4096];
221
222
223    // straight from example
224    do
225    {
226        in.read(buf, 4096);
227        n = in.gcount();
228        done = (n != 4096);
229        if (XML_Parse(p, buf, n, done) == XML_STATUS_ERROR)
230        {
231            XML_Error errorCode = XML_GetErrorCode(p);
232            int errorLine = XML_GetCurrentLineNumber(p);
233            int errorCol = XML_GetCurrentColumnNumber(p);
234            const XML_LChar *errorString = XML_ErrorString(errorCode);
235                std::stringstream errorDesc;
236            errorDesc << "XML parsing error at line " 
237                << errorLine << ":" << errorCol;
238            errorDesc << ": " << errorString;
239            error = errorDesc.str();
240            return false;
241        }
242        count += n;
243    } while (!done);
244
245    error = "";
246    return true;
247}
248
Note: See TracBrowser for help on using the repository browser.