1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00
occt/src/LDOM/LDOM_XmlWriter.cxx
ibs 4ff92abe44 0026229: Add the possibility in OCAF to open/save a document from/to a stream object
TDocStd_Application class extended to open/save a document of XmlOcaf and BinOcaf format
from/to standard SEEKABLE stream object which should support SEEK functionality.

Open and SaveAs DRAW commands got new additional argument "-stream" to turn on using of stream functionality.

The main changes for BinOcaf format applied in:
FSD_BinaryFile class (static method using standard stream added)
BinLDrivers_DocumentRetrievalDriver and BinLDrivers_DocumentStorageDriver classes use standard stream object as an argument

The main changes for XmlOcaf format applied in:
LDOMParser and LDOM_XmlWriter classes  use standard stream object as an argument

Unused class FSD_Archive and its siblings removed from MFC samples.
2015-12-17 18:03:34 +03:00

466 lines
13 KiB
C++

// Created on: 2001-06-28
// Created by: Alexander GRIGORIEV
// Copyright (c) 2001-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <LDOM_XmlWriter.hxx>
#include <LDOM_Document.hxx>
#include <LDOM_CharReference.hxx>
#define chOpenAngle '<'
#define chCloseAngle '>'
#define chOpenSquare '['
#define chCloseSquare ']'
#define chQuestion '?'
#define chForwardSlash '/'
#define chLF '\n'
#define chNull '\0'
#define chEqual '='
#define chDash '-'
#define chBang '!'
#define chSpace ' '
#define chDoubleQuote '\"'
#define chZero '0'
#define chOne '1'
#define chTwo '2'
#define chThree '3'
#define chFour '4'
#define chFive '5'
#define chSix '6'
#define chSeven '7'
#define chEight '8'
#define chNine '9'
#define chLatin_a 'a'
#define chLatin_b 'b'
#define chLatin_c 'c'
#define chLatin_d 'd'
#define chLatin_e 'e'
#define chLatin_f 'f'
#define chLatin_g 'g'
#define chLatin_h 'h'
#define chLatin_i 'i'
#define chLatin_j 'j'
#define chLatin_k 'k'
#define chLatin_l 'l'
#define chLatin_m 'm'
#define chLatin_n 'n'
#define chLatin_o 'o'
#define chLatin_p 'p'
#define chLatin_q 'q'
#define chLatin_r 'r'
#define chLatin_s 's'
#define chLatin_t 't'
#define chLatin_u 'u'
#define chLatin_v 'v'
#define chLatin_w 'w'
#define chLatin_x 'x'
#define chLatin_y 'y'
#define chLatin_z 'z'
#define chLatin_A 'A'
#define chLatin_B 'B'
#define chLatin_C 'C'
#define chLatin_D 'D'
#define chLatin_E 'E'
#define chLatin_F 'F'
#define chLatin_G 'G'
#define chLatin_H 'H'
#define chLatin_I 'I'
#define chLatin_J 'J'
#define chLatin_K 'K'
#define chLatin_L 'L'
#define chLatin_M 'M'
#define chLatin_N 'N'
#define chLatin_O 'O'
#define chLatin_P 'P'
#define chLatin_Q 'Q'
#define chLatin_R 'R'
#define chLatin_S 'S'
#define chLatin_T 'T'
#define chLatin_U 'U'
#define chLatin_V 'V'
#define chLatin_W 'W'
#define chLatin_X 'X'
#define chLatin_Y 'Y'
#define chLatin_Z 'Z'
static const char gEndElement[] = { chOpenAngle, chForwardSlash, chNull };
static const char gEndElement1[]= { chForwardSlash, chNull };
static const char gXMLDecl1[] =
{ chOpenAngle, chQuestion, chLatin_x, chLatin_m, chLatin_l
, chSpace, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_i
, chLatin_o, chLatin_n, chEqual, chDoubleQuote, chNull
};
static const char gXMLDecl2[] =
{ chDoubleQuote, chSpace, chLatin_e, chLatin_n, chLatin_c
, chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chEqual
, chDoubleQuote, chNull
};
static const char gXMLDecl4[] =
{ chDoubleQuote, chQuestion, chCloseAngle
, chLF, chNull
};
static const char gStartCDATA[] =
{ chOpenAngle, chBang, chOpenSquare, chLatin_C, chLatin_D,
chLatin_A, chLatin_T, chLatin_A, chOpenSquare, chNull
};
static const char gEndCDATA[] =
{ chCloseSquare, chCloseSquare, chCloseAngle, chNull };
static const char gStartComment[] =
{ chOpenAngle, chBang, chDash, chDash, chNull };
static const char gEndComment[] =
{ chDash, chDash, chCloseAngle, chNull };
static char* getEncodingName (const char* theEncodingName)
{
const char* anEncoding = theEncodingName;
if (theEncodingName == NULL)
{
static const char anUTFEncoding [] = {chLatin_U, chLatin_T, chLatin_F, chDash, chEight, chNull};
anEncoding = anUTFEncoding;
}
Standard_Integer aLen = 0;
while (anEncoding[aLen++] != chNull);
char * aResult = new char [aLen];
memcpy (aResult, anEncoding, aLen * sizeof (char));
return aResult;
}
//=======================================================================
//function : LDOM_XmlWriter
//purpose :
//=======================================================================
LDOM_XmlWriter::LDOM_XmlWriter (const char * theEncoding)
: myEncodingName (::getEncodingName (theEncoding)),
myIndent (0),
myCurIndent (0),
myABuffer (NULL),
myABufferLen (0)
{
;
}
//=======================================================================
//function : ~LDOM_XmlWriter
//purpose : Destructor
//=======================================================================
LDOM_XmlWriter::~LDOM_XmlWriter ()
{
delete [] myEncodingName;
if (myABuffer != NULL)
{
delete [] myABuffer;
}
}
//=======================================================================
//function : Write
//purpose :
//=======================================================================
void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOM_Document& aDoc)
{
Write (theOStream, gXMLDecl1);
const char * anXMLversion = "1.0";
Write (theOStream, anXMLversion);
Write (theOStream, gXMLDecl2);
Write (theOStream, myEncodingName);
Write (theOStream, gXMLDecl4);
Write (theOStream, aDoc.getDocumentElement());
}
//=======================================================================
//function : Write
//purpose :
//=======================================================================
void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOM_Node& theNode)
{
// Get the name and value out for convenience
LDOMString aNodeName = theNode.getNodeName();
LDOMString aNodeValue = theNode.getNodeValue();
switch (theNode.getNodeType())
{
case LDOM_Node::TEXT_NODE :
Write (theOStream, aNodeValue);
break;
case LDOM_Node::ELEMENT_NODE :
{
const int aMaxNSpaces = 40;
static char aSpaces [] = {
chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
chOpenAngle, chNull };
const char * anIndentString = &aSpaces [aMaxNSpaces - myCurIndent];
if (anIndentString < &aSpaces[0])
{
anIndentString = &aSpaces[0];
}
// Output the element start tag.
Write (theOStream, anIndentString);
Write (theOStream, aNodeName.GetString());
// Output any attributes of this element
const LDOM_Element& anElemToWrite = (const LDOM_Element&)theNode;
LDOM_NodeList aListAtt = anElemToWrite.GetAttributesList();
Standard_Integer aListInd = aListAtt.getLength();
while (aListInd--)
{
LDOM_Node aChild = aListAtt.item (aListInd);
WriteAttribute (theOStream, aChild);
}
// Test for the presence of children
LDOM_Node aChild = theNode.getFirstChild();
if (aChild != 0)
{
// There are children. Close start-tag, and output children.
Write (theOStream, chCloseAngle);
if (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE && myIndent > 0)
{
Write(theOStream, chLF);
}
Standard_Boolean isChildElem = Standard_False;
while( aChild != 0)
{
isChildElem = (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE);
if (isChildElem)
{
myCurIndent += myIndent;
}
Write(theOStream, aChild);
if (isChildElem)
{
myCurIndent -= myIndent;
}
do
{
aChild = aChild.getNextSibling();
} while (aChild.getNodeType() == LDOM_Node::ATTRIBUTE_NODE);
}
// Done with children. Output the end tag.
if (isChildElem)
{
Write (theOStream, anIndentString);
Write (theOStream, gEndElement1);
Write (theOStream, aNodeName.GetString());
Write (theOStream, chCloseAngle);
}
else
{
Write (theOStream, gEndElement);
Write (theOStream, aNodeName.GetString());
Write (theOStream, chCloseAngle);
}
}
else
{
// There were no children. Output the short form close of
// the element start tag, making it an empty-element tag.
Write (theOStream, chForwardSlash);
Write (theOStream, chCloseAngle);
}
if (myIndent > 0)
{
Write (theOStream, chLF);
}
break;
}
case LDOM_Node::CDATA_SECTION_NODE:
{
Write (theOStream, gStartCDATA);
Write (theOStream, aNodeValue);
Write (theOStream, gEndCDATA);
break;
}
case LDOM_Node::COMMENT_NODE:
{
Write (theOStream, gStartComment);
Write (theOStream, aNodeValue);
Write (theOStream, gEndComment);
break;
}
default:
#ifndef _MSC_VER
cerr << "Unrecognized node type = "
<< (long)theNode.getNodeType() << endl
#endif
; }
}
//=======================================================================
//function :
//purpose : Stream out an LDOMString
//=======================================================================
void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const LDOMBasicString& theString)
{
switch (theString.Type())
{
case LDOMBasicString::LDOM_Integer:
{
Standard_Integer aValue;
theString.GetInteger (aValue);
TCollection_AsciiString aStrValue (aValue);
theOStream.write(aStrValue.ToCString(), strlen (aStrValue.ToCString()));
break;
}
case LDOMBasicString::LDOM_AsciiHashed: // attr names and element tags
case LDOMBasicString::LDOM_AsciiDocClear:
{
const char* aStr = theString.GetString();
if (aStr)
{
const Standard_Size aLen = strlen (aStr);
if (aLen > 0)
{
theOStream.write(aStr, aLen);
}
}
}
break;
case LDOMBasicString::LDOM_AsciiFree:
case LDOMBasicString::LDOM_AsciiDoc:
{
const char* aStr = theString.GetString();
if (aStr)
{
Standard_Integer aLen;
char* encStr = LDOM_CharReference::Encode (aStr, aLen, Standard_False);
if (aLen > 0)
{
theOStream.write(encStr, aLen);
}
if (encStr != aStr)
{
delete [] encStr;
}
}
}
default: ;
}
}
//=======================================================================
//function : Write
//purpose : Stream out a char
//=======================================================================
void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const char theChar)
{
theOStream.write (&theChar, sizeof(char));
}
//=======================================================================
//function : Write
//purpose : Stream out a char *
//=======================================================================
void LDOM_XmlWriter::Write (Standard_OStream& theOStream, const char * theString)
{
Standard_Size aLength = strlen (theString);
if (aLength > 0)
{
theOStream.write (theString, aLength);
}
}
//=======================================================================
//function : WriteAttribute()
//purpose : Stream out an XML attribute.
//=======================================================================
void LDOM_XmlWriter::WriteAttribute (Standard_OStream& theOStream, const LDOM_Node& theAtt)
{
const char* aName = theAtt.getNodeName().GetString();
const LDOMString aValueStr = theAtt.getNodeValue();
int aLength = 0;
// Integer attribute value
if (aValueStr.Type() == LDOMBasicString::LDOM_Integer)
{
Standard_Integer anIntValue;
aValueStr.GetInteger (anIntValue);
aLength = (Standard_Integer)(20 + strlen (aName));
if (aLength > myABufferLen)
{
if (myABuffer != NULL)
{
delete [] myABuffer;
}
myABuffer = new char [aLength+1];
myABufferLen = aLength;
}
sprintf (myABuffer, "%c%s%c%c%d%c", chSpace, aName, chEqual, chDoubleQuote, anIntValue, chDoubleQuote);
aLength = (Standard_Integer)strlen (myABuffer);
}
else // String attribute value
{
char* encStr;
const char* aValue = aValueStr.GetString();
if (aValueStr.Type() == LDOMBasicString::LDOM_AsciiDocClear)
{
encStr = (char *) aValue;
aLength = (Standard_Integer) (4 + strlen (aValue) + strlen (aName));
}
else
{
encStr = LDOM_CharReference::Encode (aValue, aLength, Standard_True);
aLength += (Standard_Integer) (4 + strlen (aName));
}
if (aLength > myABufferLen)
{
if (myABuffer != NULL)
{
delete [] myABuffer;
}
myABuffer = new char [aLength+1];
myABufferLen = aLength;
}
sprintf (myABuffer, "%c%s%c%c%s%c", chSpace, aName, chEqual, chDoubleQuote, encStr, chDoubleQuote);
if (encStr != aValue)
{
delete [] encStr;
}
}
theOStream.write (myABuffer, aLength);
}