0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / LDOM / LDOM_XmlWriter.cxx
CommitLineData
b311480e 1// Created on: 2001-06-28
2// Created by: Alexander GRIGORIEV
973c2be1 3// Copyright (c) 2001-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#include <LDOM_XmlWriter.hxx>
17#include <LDOM_Document.hxx>
18#include <LDOM_CharReference.hxx>
19
20#define chOpenAngle '<'
21#define chCloseAngle '>'
22#define chOpenSquare '['
23#define chCloseSquare ']'
24#define chQuestion '?'
25#define chForwardSlash '/'
26#define chLF '\n'
27#define chNull '\0'
28#define chEqual '='
29#define chDash '-'
30#define chBang '!'
31#define chSpace ' '
32#define chDoubleQuote '\"'
33#define chZero '0'
34#define chOne '1'
35#define chTwo '2'
36#define chThree '3'
37#define chFour '4'
38#define chFive '5'
39#define chSix '6'
40#define chSeven '7'
41#define chEight '8'
42#define chNine '9'
43#define chLatin_a 'a'
44#define chLatin_b 'b'
45#define chLatin_c 'c'
46#define chLatin_d 'd'
47#define chLatin_e 'e'
48#define chLatin_f 'f'
49#define chLatin_g 'g'
50#define chLatin_h 'h'
51#define chLatin_i 'i'
52#define chLatin_j 'j'
53#define chLatin_k 'k'
54#define chLatin_l 'l'
55#define chLatin_m 'm'
56#define chLatin_n 'n'
57#define chLatin_o 'o'
58#define chLatin_p 'p'
59#define chLatin_q 'q'
60#define chLatin_r 'r'
61#define chLatin_s 's'
62#define chLatin_t 't'
63#define chLatin_u 'u'
64#define chLatin_v 'v'
65#define chLatin_w 'w'
66#define chLatin_x 'x'
67#define chLatin_y 'y'
68#define chLatin_z 'z'
69#define chLatin_A 'A'
70#define chLatin_B 'B'
71#define chLatin_C 'C'
72#define chLatin_D 'D'
73#define chLatin_E 'E'
74#define chLatin_F 'F'
75#define chLatin_G 'G'
76#define chLatin_H 'H'
77#define chLatin_I 'I'
78#define chLatin_J 'J'
79#define chLatin_K 'K'
80#define chLatin_L 'L'
81#define chLatin_M 'M'
82#define chLatin_N 'N'
83#define chLatin_O 'O'
84#define chLatin_P 'P'
85#define chLatin_Q 'Q'
86#define chLatin_R 'R'
87#define chLatin_S 'S'
88#define chLatin_T 'T'
89#define chLatin_U 'U'
90#define chLatin_V 'V'
91#define chLatin_W 'W'
92#define chLatin_X 'X'
93#define chLatin_Y 'Y'
94#define chLatin_Z 'Z'
95
4ff92abe 96static const char gEndElement[] = { chOpenAngle, chForwardSlash, chNull };
97static const char gEndElement1[]= { chForwardSlash, chNull };
98
99static const char gXMLDecl1[] =
7fd59977 100{ chOpenAngle, chQuestion, chLatin_x, chLatin_m, chLatin_l
101 , chSpace, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_i
102 , chLatin_o, chLatin_n, chEqual, chDoubleQuote, chNull
103};
4ff92abe 104static const char gXMLDecl2[] =
7fd59977 105{ chDoubleQuote, chSpace, chLatin_e, chLatin_n, chLatin_c
106 , chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chEqual
107 , chDoubleQuote, chNull
108};
4ff92abe 109
110static const char gXMLDecl4[] =
7fd59977 111{ chDoubleQuote, chQuestion, chCloseAngle
112 , chLF, chNull
113};
4ff92abe 114static const char gStartCDATA[] =
7fd59977 115{ chOpenAngle, chBang, chOpenSquare, chLatin_C, chLatin_D,
116 chLatin_A, chLatin_T, chLatin_A, chOpenSquare, chNull
117};
4ff92abe 118static const char gEndCDATA[] =
7fd59977 119{ chCloseSquare, chCloseSquare, chCloseAngle, chNull };
4ff92abe 120static const char gStartComment[] =
7fd59977 121{ chOpenAngle, chBang, chDash, chDash, chNull };
4ff92abe 122static const char gEndComment[] =
7fd59977 123{ chDash, chDash, chCloseAngle, chNull };
7fd59977 124
4ff92abe 125static char* getEncodingName (const char* theEncodingName)
7fd59977 126{
4ff92abe 127 const char* anEncoding = theEncodingName;
7fd59977 128 if (theEncodingName == NULL)
129 {
4ff92abe 130 static const char anUTFEncoding [] = {chLatin_U, chLatin_T, chLatin_F, chDash, chEight, chNull};
7fd59977 131 anEncoding = anUTFEncoding;
132 }
4ff92abe 133
7fd59977 134 Standard_Integer aLen = 0;
135 while (anEncoding[aLen++] != chNull);
4ff92abe 136
137 char * aResult = new char [aLen];
138 memcpy (aResult, anEncoding, aLen * sizeof (char));
139
7fd59977 140 return aResult;
141}
142
143//=======================================================================
4ff92abe 144//function : LDOM_XmlWriter
145//purpose :
7fd59977 146//=======================================================================
4ff92abe 147LDOM_XmlWriter::LDOM_XmlWriter (const char * theEncoding)
148 : myEncodingName (::getEncodingName (theEncoding)),
149 myIndent (0),
150 myCurIndent (0),
151 myABuffer (NULL),
152 myABufferLen (0)
153{
154 ;
155}
7fd59977 156
157//=======================================================================
158//function : ~LDOM_XmlWriter
159//purpose : Destructor
160//=======================================================================
7fd59977 161LDOM_XmlWriter::~LDOM_XmlWriter ()
162{
163 delete [] myEncodingName;
7fd59977 164
4ff92abe 165 if (myABuffer != NULL)
166 {
167 delete [] myABuffer;
7fd59977 168 }
7fd59977 169}
170
171//=======================================================================
4ff92abe 172//function : Write
173//purpose :
7fd59977 174//=======================================================================
4ff92abe 175void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOM_Document& aDoc)
7fd59977 176{
4ff92abe 177 Write (theOStream, gXMLDecl1);
7fd59977 178
4ff92abe 179 const char * anXMLversion = "1.0";
180 Write (theOStream, anXMLversion);
7fd59977 181
4ff92abe 182 Write (theOStream, gXMLDecl2);
183 Write (theOStream, myEncodingName);
184 Write (theOStream, gXMLDecl4);
7fd59977 185
4ff92abe 186 Write (theOStream, aDoc.getDocumentElement());
7fd59977 187}
188
189//=======================================================================
4ff92abe 190//function : Write
191//purpose :
7fd59977 192//=======================================================================
4ff92abe 193void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOM_Node& theNode)
7fd59977 194{
195 // Get the name and value out for convenience
4ff92abe 196 LDOMString aNodeName = theNode.getNodeName();
197 LDOMString aNodeValue = theNode.getNodeValue();
7fd59977 198
4ff92abe 199 switch (theNode.getNodeType())
7fd59977 200 {
4ff92abe 201 case LDOM_Node::TEXT_NODE :
202 Write (theOStream, aNodeValue);
7fd59977 203 break;
4ff92abe 204 case LDOM_Node::ELEMENT_NODE :
7fd59977 205 {
206 const int aMaxNSpaces = 40;
4ff92abe 207 static char aSpaces [] = {
7fd59977 208 chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
209 chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
210 chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
211 chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
212 chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
213 chOpenAngle, chNull };
4ff92abe 214 const char * anIndentString = &aSpaces [aMaxNSpaces - myCurIndent];
215
216 if (anIndentString < &aSpaces[0])
217 {
218 anIndentString = &aSpaces[0];
219 }
7fd59977 220
221 // Output the element start tag.
4ff92abe 222 Write (theOStream, anIndentString);
223 Write (theOStream, aNodeName.GetString());
7fd59977 224
4ff92abe 225 // Output any attributes of this element
226 const LDOM_Element& anElemToWrite = (const LDOM_Element&)theNode;
227 LDOM_NodeList aListAtt = anElemToWrite.GetAttributesList();
7fd59977 228 Standard_Integer aListInd = aListAtt.getLength();
4ff92abe 229
230 while (aListInd--)
231 {
7fd59977 232 LDOM_Node aChild = aListAtt.item (aListInd);
4ff92abe 233 WriteAttribute (theOStream, aChild);
7fd59977 234 }
235
236 // Test for the presence of children
4ff92abe 237 LDOM_Node aChild = theNode.getFirstChild();
7fd59977 238 if (aChild != 0)
239 {
240 // There are children. Close start-tag, and output children.
4ff92abe 241 Write (theOStream, chCloseAngle);
7fd59977 242 if (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE && myIndent > 0)
4ff92abe 243 {
244 Write(theOStream, chLF);
245 }
246
7fd59977 247 Standard_Boolean isChildElem = Standard_False;
248 while( aChild != 0)
249 {
250 isChildElem = (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE);
4ff92abe 251 if (isChildElem)
252 {
253 myCurIndent += myIndent;
254 }
255
256 Write(theOStream, aChild);
257
258 if (isChildElem)
259 {
260 myCurIndent -= myIndent;
261 }
262
263 do
264 {
265 aChild = aChild.getNextSibling();
266 } while (aChild.getNodeType() == LDOM_Node::ATTRIBUTE_NODE);
7fd59977 267 }
4ff92abe 268
7fd59977 269 // Done with children. Output the end tag.
7fd59977 270 if (isChildElem)
4ff92abe 271 {
272 Write (theOStream, anIndentString);
273 Write (theOStream, gEndElement1);
274 Write (theOStream, aNodeName.GetString());
275 Write (theOStream, chCloseAngle);
276 }
7fd59977 277 else
4ff92abe 278 {
279 Write (theOStream, gEndElement);
280 Write (theOStream, aNodeName.GetString());
281 Write (theOStream, chCloseAngle);
282 }
7fd59977 283 }
284 else
285 {
286 // There were no children. Output the short form close of
287 // the element start tag, making it an empty-element tag.
4ff92abe 288 Write (theOStream, chForwardSlash);
289 Write (theOStream, chCloseAngle);
7fd59977 290 }
4ff92abe 291
7fd59977 292 if (myIndent > 0)
4ff92abe 293 {
294 Write (theOStream, chLF);
295 }
7fd59977 296 break;
297 }
298 case LDOM_Node::CDATA_SECTION_NODE:
299 {
4ff92abe 300 Write (theOStream, gStartCDATA);
301 Write (theOStream, aNodeValue);
302 Write (theOStream, gEndCDATA);
7fd59977 303 break;
304 }
305 case LDOM_Node::COMMENT_NODE:
306 {
4ff92abe 307 Write (theOStream, gStartComment);
308 Write (theOStream, aNodeValue);
309 Write (theOStream, gEndComment);
7fd59977 310 break;
311 }
312 default:
57c28b61 313#ifndef _MSC_VER
7fd59977 314 cerr << "Unrecognized node type = "
4ff92abe 315 << (long)theNode.getNodeType() << endl
7fd59977 316#endif
317 ; }
4ff92abe 318}
319
320//=======================================================================
321//function :
322//purpose : Stream out an LDOMString
323//=======================================================================
324void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOMBasicString& theString)
325{
326 switch (theString.Type())
327 {
328 case LDOMBasicString::LDOM_Integer:
329 {
330 Standard_Integer aValue;
331 theString.GetInteger (aValue);
332
333 TCollection_AsciiString aStrValue (aValue);
334 theOStream.write(aStrValue.ToCString(), strlen (aStrValue.ToCString()));
335
336 break;
337 }
338 case LDOMBasicString::LDOM_AsciiHashed: // attr names and element tags
339 case LDOMBasicString::LDOM_AsciiDocClear:
340 {
341 const char* aStr = theString.GetString();
342 if (aStr)
343 {
344 const Standard_Size aLen = strlen (aStr);
345 if (aLen > 0)
346 {
347 theOStream.write(aStr, aLen);
348 }
349 }
350 }
351 break;
352 case LDOMBasicString::LDOM_AsciiFree:
353 case LDOMBasicString::LDOM_AsciiDoc:
354 {
355 const char* aStr = theString.GetString();
356 if (aStr)
357 {
358 Standard_Integer aLen;
359 char* encStr = LDOM_CharReference::Encode (aStr, aLen, Standard_False);
360 if (aLen > 0)
361 {
362 theOStream.write(encStr, aLen);
363 }
364
365 if (encStr != aStr)
366 {
367 delete [] encStr;
368 }
369 }
370 }
371 default: ;
372 }
373}
374
375//=======================================================================
376//function : Write
377//purpose : Stream out a char
378//=======================================================================
379void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const char theChar)
380{
381 theOStream.write (&theChar, sizeof(char));
382}
383
384//=======================================================================
385//function : Write
386//purpose : Stream out a char *
387//=======================================================================
388void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const char * theString)
389{
390 Standard_Size aLength = strlen (theString);
391 if (aLength > 0)
392 {
393 theOStream.write (theString, aLength);
394 }
395}
396
397//=======================================================================
398//function : WriteAttribute()
399//purpose : Stream out an XML attribute.
400//=======================================================================
401void LDOM_XmlWriter::WriteAttribute (Standard_OStream& theOStream, const LDOM_Node& theAtt)
402{
403 const char* aName = theAtt.getNodeName().GetString();
404 const LDOMString aValueStr = theAtt.getNodeValue();
405
406 int aLength = 0;
407
408 // Integer attribute value
409 if (aValueStr.Type() == LDOMBasicString::LDOM_Integer)
410 {
411 Standard_Integer anIntValue;
412 aValueStr.GetInteger (anIntValue);
413
414 aLength = (Standard_Integer)(20 + strlen (aName));
415 if (aLength > myABufferLen)
416 {
417 if (myABuffer != NULL)
418 {
419 delete [] myABuffer;
420 }
421
422 myABuffer = new char [aLength+1];
423 myABufferLen = aLength;
424 }
425 sprintf (myABuffer, "%c%s%c%c%d%c", chSpace, aName, chEqual, chDoubleQuote, anIntValue, chDoubleQuote);
426 aLength = (Standard_Integer)strlen (myABuffer);
427
428
429 }
430 else // String attribute value
431 {
432 char* encStr;
433 const char* aValue = aValueStr.GetString();
434 if (aValueStr.Type() == LDOMBasicString::LDOM_AsciiDocClear)
435 {
436 encStr = (char *) aValue;
437 aLength = (Standard_Integer) (4 + strlen (aValue) + strlen (aName));
438 }
439 else
440 {
441 encStr = LDOM_CharReference::Encode (aValue, aLength, Standard_True);
442 aLength += (Standard_Integer) (4 + strlen (aName));
443 }
444
445 if (aLength > myABufferLen)
446 {
447 if (myABuffer != NULL)
448 {
449 delete [] myABuffer;
450 }
451
452 myABuffer = new char [aLength+1];
453 myABufferLen = aLength;
454 }
455
456 sprintf (myABuffer, "%c%s%c%c%s%c", chSpace, aName, chEqual, chDoubleQuote, encStr, chDoubleQuote);
457
458 if (encStr != aValue)
459 {
460 delete [] encStr;
461 }
462 }
463
464 theOStream.write (myABuffer, aLength);
7fd59977 465}