1 // Created on: 2001-07-20
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 //AGV 060302: Input from istream
17 // AGV 130302: Return error if there are data after the root element
19 //#define LDOM_PARSER_TRACE
21 #include <LDOMParser.hxx>
22 #include <LDOM_MemManager.hxx>
23 #include <LDOM_XmlReader.hxx>
24 #include <LDOM_BasicText.hxx>
25 #include <LDOM_CharReference.hxx>
26 #include <TCollection_ExtendedString.hxx>
35 //=======================================================================
36 //function : ~LDOMParser
38 //=======================================================================
40 LDOMParser::~LDOMParser()
42 if (myReader) delete myReader;
45 //=======================================================================
46 //function : ReadRecord
47 //purpose : Take the next lexical element from XML stream
48 //=======================================================================
50 #ifdef LDOM_PARSER_TRACE
55 LDOM_XmlReader::RecordType ReadRecord (LDOM_XmlReader& aReader,
58 #ifdef LDOM_PARSER_TRACE
62 const LDOM_XmlReader::RecordType aType = aReader.ReadRecord (aData);
63 #ifdef LDOM_PARSER_TRACE
64 static FILE * ff = NULL;
65 TCollection_AsciiString aTraceFileName;
67 aTraceFileName = TCollection_AsciiString (getenv("TEMP")) + "\\ldom.trace";
69 aTraceFileName = "/tmp/ldom.trace";
71 ff = fopen (aTraceFileName.ToCString(),ff ? "at": "wt");
72 const char * aDataType;
74 case LDOM_XmlReader::XML_UNKNOWN: aDataType= "XML_UNKNOWN "; break;
75 case LDOM_XmlReader::XML_HEADER: aDataType= "XML_HEADER "; break;
76 case LDOM_XmlReader::XML_DOCTYPE: aDataType= "XML_DOCTYPE "; break;
77 case LDOM_XmlReader::XML_COMMENT: aDataType= "XML_COMMENT "; break;
78 case LDOM_XmlReader::XML_START_ELEMENT: aDataType= "XML_START_ELEMENT"; break;
79 case LDOM_XmlReader::XML_END_ELEMENT: aDataType= "XML_END_ELEMENT "; break;
80 case LDOM_XmlReader::XML_FULL_ELEMENT: aDataType= "XML_FULL_ELEMENT "; break;
81 case LDOM_XmlReader::XML_TEXT: aDataType= "XML_TEXT "; break;
82 case LDOM_XmlReader::XML_CDATA: aDataType= "XML_CDATA "; break;
83 case LDOM_XmlReader::XML_EOF: aDataType= "XML_EOF ";
85 char * aStr = aData.str();
86 fprintf (ff, "%5d %s: %s\n", aCounter, aDataType, aStr);
93 //=======================================================================
95 //purpose : Return text describing a parsing error
96 //=======================================================================
98 const TCollection_AsciiString& LDOMParser::GetError
99 (TCollection_AsciiString& aData) const
101 char * aStr =(char *)myCurrentData.str();
107 //=======================================================================
110 //=======================================================================
112 Standard_Boolean LDOMParser::parse (istream& anInput)
114 // Open the DOM Document
115 myDocument = new LDOM_MemManager (20000);
118 // Create the Reader instance
119 if (myReader) delete myReader;
120 myReader = new LDOM_XmlReader (anInput, myDocument, myError);
123 return ParseDocument();
126 //=======================================================================
129 //=======================================================================
131 Standard_Boolean LDOMParser::parse (const char * const aFileName)
133 // Open the DOM Document
134 myDocument = new LDOM_MemManager (20000);
139 TCollection_ExtendedString aFileNameW(aFileName, Standard_True);
140 int aFile = _wopen ((const wchar_t*) aFileNameW.ToExtString(), O_RDONLY);
142 int aFile = open (aFileName, O_RDONLY);
145 myError = "Fatal XML error: Cannot open XML file";
146 return Standard_True;
149 // Create the Reader instance
150 if (myReader) delete myReader;
151 myReader = new LDOM_XmlReader (aFile, myDocument, myError);
154 Standard_Boolean isError = ParseDocument();
159 //=======================================================================
160 //function : ParseDocument
161 //purpose : parse the whole document (abstracted from the XML source)
162 //=======================================================================
164 Standard_Boolean LDOMParser::ParseDocument ()
166 Standard_Boolean isError = Standard_False;
167 Standard_Boolean isElement = Standard_False;
168 Standard_Boolean isDoctype = Standard_False;
171 LDOM_XmlReader::RecordType aType = ReadRecord (*myReader, myCurrentData);
173 case LDOM_XmlReader::XML_HEADER:
174 if (isDoctype || isElement) {
175 myError = "Unexpected XML declaration";
176 isError = Standard_True;
180 case LDOM_XmlReader::XML_DOCTYPE:
182 myError = "Unexpected DOCTYPE declaration";
183 isError = Standard_True;
186 isDoctype = Standard_True;
187 case LDOM_XmlReader::XML_COMMENT:
189 case LDOM_XmlReader::XML_FULL_ELEMENT:
190 if (isElement == Standard_False) {
191 isElement = Standard_True;
192 myDocument -> myRootElement = &myReader -> GetElement ();
193 if (startElement()) {
194 isError = Standard_True;
195 myError = "User abort at startElement()";
199 isError = Standard_True;
200 myError = "User abort at endElement()";
205 case LDOM_XmlReader::XML_START_ELEMENT:
206 if (isElement == Standard_False) {
207 isElement = Standard_True;
208 myDocument -> myRootElement = &myReader -> GetElement ();
209 if (startElement()) {
210 isError = Standard_True;
211 myError = "User abort at startElement()";
214 isError = ParseElement ();
218 isError = Standard_True;
219 myError = "Expected comment or end-of-file";
220 case LDOM_XmlReader::XML_END_ELEMENT:
222 isError = Standard_True;
223 myError = "User abort at endElement()";
225 case LDOM_XmlReader::XML_EOF:
227 case LDOM_XmlReader::XML_UNKNOWN:
230 myError = "Unexpected data beyond the Document Element";
232 isError = Standard_True;
239 //=======================================================================
240 //function : ParseElement
241 //purpose : parse one element, given the type of its XML presentation
242 //=======================================================================
244 Standard_Boolean LDOMParser::ParseElement ()
246 Standard_Boolean isError = Standard_False;
247 const LDOM_BasicElement * aParent = &myReader->GetElement();
248 const LDOM_BasicNode * aLastChild = NULL;
250 LDOM_Node::NodeType aLocType;
251 LDOMBasicString aTextValue;
253 LDOM_XmlReader::RecordType aType = ReadRecord (* myReader, myCurrentData);
255 case LDOM_XmlReader::XML_UNKNOWN:
256 isError = Standard_True;
258 case LDOM_XmlReader::XML_FULL_ELEMENT:
259 aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
260 if (startElement()) {
261 isError = Standard_True;
262 myError = "User abort at startElement()";
266 isError = Standard_True;
267 myError = "User abort at endElement()";
271 case LDOM_XmlReader::XML_START_ELEMENT:
272 aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
273 if (startElement()) {
274 isError = Standard_True;
275 myError = "User abort at startElement()";
278 isError = ParseElement ();
280 case LDOM_XmlReader::XML_END_ELEMENT:
282 Standard_CString aParentName = Standard_CString(aParent->GetTagName());
283 aTextStr = (char *)myCurrentData.str();
284 if (strcmp(aTextStr, aParentName) != 0) {
285 myError = "Expected end tag \'";
286 myError += aParentName;
288 isError = Standard_True;
290 else if (endElement()) {
291 isError = Standard_True;
292 myError = "User abort at endElement()";
297 case LDOM_XmlReader::XML_TEXT:
298 aLocType = LDOM_Node::TEXT_NODE;
300 Standard_Integer aTextLen;
301 aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
302 // try to convert to integer
303 if (IsDigit(aTextStr[0])) {
304 if (LDOM_XmlReader::getInteger (aTextValue, aTextStr,
305 aTextStr + aTextLen))
306 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
308 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
310 goto create_text_node;
311 case LDOM_XmlReader::XML_COMMENT:
312 aLocType = LDOM_Node::COMMENT_NODE;
314 Standard_Integer aTextLen;
315 aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
316 aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
318 goto create_text_node;
319 case LDOM_XmlReader::XML_CDATA:
320 aLocType = LDOM_Node::CDATA_SECTION_NODE;
321 aTextStr = (char *)myCurrentData.str();
322 aTextValue = LDOMBasicString(aTextStr,myCurrentData.Length(),myDocument);
325 LDOM_BasicNode& aTextNode =
326 LDOM_BasicText::Create (aLocType, aTextValue, myDocument);
327 aParent -> AppendChild (&aTextNode, aLastChild);
331 case LDOM_XmlReader::XML_EOF:
332 myError = "Inexpected end of file";
333 isError = Standard_True;
342 //=======================================================================
343 //function : startElement
344 //purpose : virtual hook on 'StartElement' event for descendant classes
345 //=======================================================================
347 Standard_Boolean LDOMParser::startElement ()
349 return Standard_False;
352 //=======================================================================
353 //function : endElement
354 //purpose : virtual hook on 'EndElement' event for descendant classes
355 //=======================================================================
357 Standard_Boolean LDOMParser::endElement ()
359 return Standard_False;
362 //=======================================================================
363 //function : getCurrentElement
365 //=======================================================================
367 LDOM_Element LDOMParser::getCurrentElement () const
369 return LDOM_Element (myReader -> GetElement(), myDocument);
372 //=======================================================================
373 //function : getDocument
375 //=======================================================================
377 LDOM_Document LDOMParser::getDocument ()
379 return myDocument -> Self();