moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kvoctrain / kvoctrain / kvt-core / kvt-xml / XmlReader.cpp
blob81d1aba6a207870b66af55f59af6f4dfd33dc993
1 /* -*- C++ -*-
3 $Id$
5 This file is part of KIllustrator.
6 Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
8 modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ยด99
10 -----------------------------------------------------------------------
12 -----------------------------------------------------------------------
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU Library General Public License as
16 published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU Library General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <iostream>
32 using namespace std;
33 #include "XmlReader.h"
35 XmlReader::XmlReader (KOXML_ISTREAM& is)
36 : tokenizer (is)
40 XmlReader::~XmlReader () {
43 bool XmlReader::validHeader () {
44 // Check for: <? xml version="1.0" ?>
45 if (tokenizer.nextToken () != XmlTokenizer::Tok_Lt)
46 return false;
47 if (tokenizer.nextToken () != XmlTokenizer::Tok_QSign)
48 return false;
50 if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
51 return false;
52 else if (tokenizer.element () != "xml")
53 return false;
55 if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
56 return false;
57 else if (tokenizer.element () != "version")
58 return false;
59 if (tokenizer.nextToken () != XmlTokenizer::Tok_Eq)
60 return false;
61 if (tokenizer.nextToken () != XmlTokenizer::Tok_String)
62 return false;
63 else if (tokenizer.element () != "1.0")
64 return false;
66 if (tokenizer.nextToken () != XmlTokenizer::Tok_QSign)
67 return false;
68 if (tokenizer.nextToken () != XmlTokenizer::Tok_Gt)
69 return false;
71 // Check for: <(!)doctype symbol system string>
73 if (tokenizer.nextToken () != XmlTokenizer::Tok_Lt)
74 return false;
76 XmlTokenizer::Token token = tokenizer.nextToken ();
77 if (token == XmlTokenizer::Tok_Exclam)
78 token = tokenizer.nextToken ();
80 if (token != XmlTokenizer::Tok_Symbol)
81 return false;
82 else if (tokenizer.element().lower() != "doctype")
83 return false;
85 if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
86 return false;
87 s_dtype = tokenizer.element ();
89 if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
90 return false;
91 else if (tokenizer.element().lower() != "system")
92 return false;
94 if (tokenizer.nextToken () != XmlTokenizer::Tok_String)
95 return false;
96 s_dtd = tokenizer.element ();
98 if (tokenizer.nextToken () != XmlTokenizer::Tok_Gt)
99 return false;
101 return true;
104 const KOXML_STRING& XmlReader::doctype () const {
105 return s_dtype;
108 const KOXML_STRING& XmlReader::dtd () const {
109 return s_dtd;
112 const KOXML_STRING& XmlReader::getText () {
113 return text;
116 bool XmlReader::readElement (XmlElement& elem) {
117 XmlTokenizer::Token tok;
118 bool result = false;
119 bool ready = false;
121 elem.reset ();
123 while (! ready) {
124 tok = tokenizer.nextToken ();
125 if (tok == XmlTokenizer::Tok_Lt) {
126 tok = tokenizer.nextToken ();
127 if (tok == XmlTokenizer::Tok_Comment) {
128 // skip comment
130 else {
131 if (tok == XmlTokenizer::Tok_Slash)
132 result = parseEndElement (elem);
133 else if (tok == XmlTokenizer::Tok_Symbol)
134 result = parseElement (tokenizer.element (), elem);
135 else if (tok == XmlTokenizer::Tok_EOF)
136 result = false;
137 ready = true;
140 else if (tok == XmlTokenizer::Tok_Text) {
141 elem.tagId = "#PCDATA";
142 text = tokenizer.element ();
143 result = true;
144 ready = true;
146 else
147 return false;
149 return result;
152 bool XmlReader::parseEndElement (XmlElement& elem) {
153 bool result = false;
155 XmlTokenizer::Token tok = tokenizer.nextToken ();
156 if (tok == XmlTokenizer::Tok_Symbol) {
157 KOXML_STRING tag = tokenizer.element ();
158 tok = tokenizer.nextToken ();
159 if (tok == XmlTokenizer::Tok_Gt) {
160 elem.tagId = tag;
161 elem.endTag = true;
162 elem.closed = true;
163 result = true;
166 return result;
169 bool XmlReader::parseElement (const KOXML_STRING& id, XmlElement& elem) {
170 KOXML_STRING tag = id;
171 bool closed = false;
172 std::list<XmlAttribute> attrib_list;
174 XmlTokenizer::Token tok = tokenizer.nextToken ();
175 while (tok != XmlTokenizer::Tok_Gt) {
176 if (tok == XmlTokenizer::Tok_Slash) {
177 if (closed)
178 return false;
179 else
180 closed = true;
182 else if (tok == XmlTokenizer::Tok_Symbol) {
183 if (! attrib_list.empty () || closed)
184 return false;
185 tokenizer.unget ();
186 if (! readAttributes (attrib_list))
187 return false;
189 else
190 return false;
192 tok = tokenizer.nextToken ();
194 elem.tagId = tag;
195 elem.endTag = false;
196 elem.closed = closed;
197 elem.attribs = attrib_list;
198 return true;
201 bool XmlReader::readAttributes (std::list<XmlAttribute>& attrib_list) {
202 XmlTokenizer::Token tok = tokenizer.nextToken ();
204 while (tok != XmlTokenizer::Tok_Gt) {
205 if (tok == XmlTokenizer::Tok_Symbol) {
206 KOXML_STRING id = tokenizer.element ();
207 if (tokenizer.nextToken () == XmlTokenizer::Tok_Eq) {
208 if (tokenizer.nextToken () == XmlTokenizer::Tok_String) {
210 // un-escape dangerous characters in reverted order
211 KOXML_STRING val = tokenizer.element();
212 int pos = 0;
213 while ((pos = val.find("&quot;", pos)) >= 0) {
214 KOXML_STRING_REMOVE( val, pos, 6);
215 KOXML_STRING_INSERT( val, pos, "\"");
216 pos += 1; // skip "
218 pos = 0;
219 while ((pos = val.find("&lf;", pos)) >= 0) {
220 KOXML_STRING_REMOVE( val, pos, 4);
221 KOXML_STRING_INSERT( val, pos, "\r");
222 pos += 1; // skip \r
224 pos = 0;
225 while ((pos = val.find("&nl;", pos)) >= 0) {
226 KOXML_STRING_REMOVE( val, pos, 4);
227 KOXML_STRING_INSERT( val, pos, "\n");
228 pos += 1; // skip \n
230 pos = 0;
231 while ((pos = val.find("&lt;", pos)) >= 0) {
232 KOXML_STRING_REMOVE( val, pos, 4);
233 KOXML_STRING_INSERT( val, pos, "<");
234 pos += 1; // skip <
236 pos = 0;
237 while ((pos = val.find ("&amp;", pos)) >= 0) {
238 KOXML_STRING_REMOVE( val, pos+1, 4);
239 pos += 1; // skip &
242 XmlAttribute attrib (id, val);
243 attrib_list.push_back (attrib);
245 else {
246 cerr << "invalid attribute value" << endl;
247 return false;
250 else {
251 cerr << "missing '='" << endl;
252 return false;
255 else if (tok == XmlTokenizer::Tok_Slash) {
256 break;
258 else {
259 cerr << "invalid attribute name: " << (int) tok << endl;
260 return false;
262 tok = tokenizer.nextToken ();
264 tokenizer.unget ();
265 return true;