mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-05-11 10:44:53 +03:00
367 lines
11 KiB
C++
Executable File
367 lines
11 KiB
C++
Executable File
// File: LDOMParser.cxx
|
|
// Created: 20.07.01 14:58:24
|
|
// Author: Alexander GRIGORIEV
|
|
// Copyright: OpenCascade 2001
|
|
// History: AGV 060302: Input from istream
|
|
// AGV 130302: Return error if there are data after the root element
|
|
|
|
//#define LDOM_PARSER_TRACE
|
|
|
|
#include <LDOMParser.hxx>
|
|
#include <LDOM_MemManager.hxx>
|
|
#include <LDOM_XmlReader.hxx>
|
|
#include <LDOM_BasicText.hxx>
|
|
#include <LDOM_CharReference.hxx>
|
|
|
|
#include <fcntl.h>
|
|
#ifdef WNT
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
//=======================================================================
|
|
//function : ~LDOMParser
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
LDOMParser::~LDOMParser()
|
|
{
|
|
if (myReader) delete myReader;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ReadRecord
|
|
//purpose : Take the next lexical element from XML stream
|
|
//=======================================================================
|
|
|
|
#ifdef LDOM_PARSER_TRACE
|
|
static
|
|
#else
|
|
inline
|
|
#endif
|
|
LDOM_XmlReader::RecordType ReadRecord (LDOM_XmlReader& aReader,
|
|
LDOM_OSStream& aData)
|
|
{
|
|
#ifdef LDOM_PARSER_TRACE
|
|
static aCounter = 0;
|
|
++ aCounter;
|
|
#endif
|
|
const LDOM_XmlReader::RecordType aType = aReader.ReadRecord (aData);
|
|
#ifdef LDOM_PARSER_TRACE
|
|
static FILE * ff = NULL;
|
|
TCollection_AsciiString aTraceFileName;
|
|
#ifdef WNT
|
|
aTraceFileName = TCollection_AsciiString (getenv("TEMP")) + "\\ldom.trace";
|
|
#else
|
|
aTraceFileName = "/tmp/ldom.trace";
|
|
#endif
|
|
ff = fopen (aTraceFileName.ToCString(),ff ? "at": "wt");
|
|
const char * aDataType;
|
|
switch (aType) {
|
|
case LDOM_XmlReader::XML_UNKNOWN: aDataType= "XML_UNKNOWN "; break;
|
|
case LDOM_XmlReader::XML_HEADER: aDataType= "XML_HEADER "; break;
|
|
case LDOM_XmlReader::XML_DOCTYPE: aDataType= "XML_DOCTYPE "; break;
|
|
case LDOM_XmlReader::XML_COMMENT: aDataType= "XML_COMMENT "; break;
|
|
case LDOM_XmlReader::XML_START_ELEMENT: aDataType= "XML_START_ELEMENT"; break;
|
|
case LDOM_XmlReader::XML_END_ELEMENT: aDataType= "XML_END_ELEMENT "; break;
|
|
case LDOM_XmlReader::XML_FULL_ELEMENT: aDataType= "XML_FULL_ELEMENT "; break;
|
|
case LDOM_XmlReader::XML_TEXT: aDataType= "XML_TEXT "; break;
|
|
case LDOM_XmlReader::XML_CDATA: aDataType= "XML_CDATA "; break;
|
|
case LDOM_XmlReader::XML_EOF: aDataType= "XML_EOF ";
|
|
}
|
|
char * aStr = aData.str();
|
|
fprintf (ff, "%5d %s: %s\n", aCounter, aDataType, aStr);
|
|
delete [] aStr;
|
|
fclose (ff);
|
|
#endif
|
|
return aType;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetError
|
|
//purpose : Return text describing a parsing error
|
|
//=======================================================================
|
|
|
|
const TCollection_AsciiString& LDOMParser::GetError
|
|
(TCollection_AsciiString& aData) const
|
|
{
|
|
char * aStr =(char *)myCurrentData.str();
|
|
aData = aStr;
|
|
delete [] aStr;
|
|
return myError;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : parse
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::parse (istream& anInput)
|
|
{
|
|
// Open the DOM Document
|
|
myDocument = new LDOM_MemManager (20000);
|
|
myError.Clear();
|
|
|
|
// Create the Reader instance
|
|
if (myReader) delete myReader;
|
|
myReader = new LDOM_XmlReader (anInput, myDocument, myError);
|
|
|
|
// Parse
|
|
return ParseDocument();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : parse
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::parse (const char * const aFileName)
|
|
{
|
|
// Open the DOM Document
|
|
myDocument = new LDOM_MemManager (20000);
|
|
myError.Clear ();
|
|
|
|
// Open the file
|
|
int aFile = open (aFileName, O_RDONLY);
|
|
if (aFile < 0) {
|
|
myError = "Fatal XML error: Cannot open XML file";
|
|
return Standard_True;
|
|
}
|
|
|
|
// Create the Reader instance
|
|
if (myReader) delete myReader;
|
|
myReader = new LDOM_XmlReader (aFile, myDocument, myError);
|
|
|
|
// Parse
|
|
Standard_Boolean isError = ParseDocument();
|
|
close (aFile);
|
|
return isError;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ParseDocument
|
|
//purpose : parse the whole document (abstracted from the XML source)
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::ParseDocument ()
|
|
{
|
|
Standard_Boolean isError = Standard_False;
|
|
Standard_Boolean isElement = Standard_False;
|
|
Standard_Boolean isHeader = Standard_False;
|
|
Standard_Boolean isDoctype = Standard_False;
|
|
|
|
while (1) {
|
|
LDOM_XmlReader::RecordType aType = ReadRecord (*myReader, myCurrentData);
|
|
switch (aType) {
|
|
case LDOM_XmlReader::XML_HEADER:
|
|
if (isDoctype || isElement) {
|
|
myError = "Unexpected XML declaration";
|
|
isError = Standard_True;
|
|
break;
|
|
}
|
|
isHeader = Standard_True;
|
|
continue;
|
|
case LDOM_XmlReader::XML_DOCTYPE:
|
|
if (isElement) {
|
|
myError = "Unexpected DOCTYPE declaration";
|
|
isError = Standard_True;
|
|
break;
|
|
}
|
|
isDoctype = Standard_True;
|
|
case LDOM_XmlReader::XML_COMMENT:
|
|
continue;
|
|
case LDOM_XmlReader::XML_FULL_ELEMENT:
|
|
if (isElement == Standard_False) {
|
|
isElement = Standard_True;
|
|
myDocument -> myRootElement = &myReader -> GetElement ();
|
|
if (startElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at startElement()";
|
|
break;
|
|
}
|
|
if (endElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at endElement()";
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
case LDOM_XmlReader::XML_START_ELEMENT:
|
|
if (isElement == Standard_False) {
|
|
isElement = Standard_True;
|
|
myDocument -> myRootElement = &myReader -> GetElement ();
|
|
if (startElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at startElement()";
|
|
break;
|
|
}
|
|
isError = ParseElement ();
|
|
if (isError) break;
|
|
continue;
|
|
}
|
|
isError = Standard_True;
|
|
myError = "Expected comment or end-of-file";
|
|
case LDOM_XmlReader::XML_END_ELEMENT:
|
|
if (endElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at endElement()";
|
|
}
|
|
case LDOM_XmlReader::XML_EOF:
|
|
break;
|
|
case LDOM_XmlReader::XML_UNKNOWN:
|
|
if (isElement) {
|
|
default:
|
|
myError = "Unexpected data beyond the Document Element";
|
|
}
|
|
isError = Standard_True;
|
|
}
|
|
break;
|
|
}
|
|
return isError;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ParseElement
|
|
//purpose : parse one element, given the type of its XML presentation
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::ParseElement ()
|
|
{
|
|
Standard_Boolean isError = Standard_False;
|
|
const LDOM_BasicElement * aParent = &myReader->GetElement();
|
|
const LDOM_BasicNode * aLastChild = NULL;
|
|
while (1) {
|
|
LDOM_Node::NodeType aLocType;
|
|
LDOMBasicString aTextValue;
|
|
char *aTextStr;
|
|
LDOM_XmlReader::RecordType aType = ReadRecord (* myReader, myCurrentData);
|
|
switch (aType) {
|
|
case LDOM_XmlReader::XML_UNKNOWN:
|
|
isError = Standard_True;
|
|
break;
|
|
case LDOM_XmlReader::XML_FULL_ELEMENT:
|
|
aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
|
|
if (startElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at startElement()";
|
|
break;
|
|
}
|
|
if (endElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at endElement()";
|
|
break;
|
|
}
|
|
break;
|
|
case LDOM_XmlReader::XML_START_ELEMENT:
|
|
aParent -> AppendChild (&myReader -> GetElement(), aLastChild);
|
|
if (startElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at startElement()";
|
|
break;
|
|
}
|
|
isError = ParseElement ();
|
|
break;
|
|
case LDOM_XmlReader::XML_END_ELEMENT:
|
|
{
|
|
Standard_CString aParentName = Standard_CString(aParent->GetTagName());
|
|
aTextStr = (char *)myCurrentData.str();
|
|
if (strcmp(aTextStr, aParentName) != 0) {
|
|
myError = "Expected end tag \'";
|
|
myError += aParentName;
|
|
myError += "\'";
|
|
isError = Standard_True;
|
|
}
|
|
else if (endElement()) {
|
|
isError = Standard_True;
|
|
myError = "User abort at endElement()";
|
|
}
|
|
delete [] aTextStr;
|
|
}
|
|
return isError;
|
|
case LDOM_XmlReader::XML_TEXT:
|
|
aLocType = LDOM_Node::TEXT_NODE;
|
|
{
|
|
Standard_Integer aTextLen;
|
|
aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
|
|
// try to convert to integer
|
|
if (IsDigit(aTextStr[0])) {
|
|
if (LDOM_XmlReader::getInteger (aTextValue, aTextStr,
|
|
aTextStr + aTextLen))
|
|
aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
|
|
} else
|
|
aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
|
|
}
|
|
goto create_text_node;
|
|
case LDOM_XmlReader::XML_COMMENT:
|
|
aLocType = LDOM_Node::COMMENT_NODE;
|
|
{
|
|
Standard_Integer aTextLen;
|
|
aTextStr = LDOM_CharReference::Decode ((char *)myCurrentData.str(), aTextLen);
|
|
aTextValue = LDOMBasicString (aTextStr, aTextLen, myDocument);
|
|
}
|
|
goto create_text_node;
|
|
case LDOM_XmlReader::XML_CDATA:
|
|
aLocType = LDOM_Node::CDATA_SECTION_NODE;
|
|
aTextStr = (char *)myCurrentData.str();
|
|
aTextValue = LDOMBasicString(aTextStr,myCurrentData.Length(),myDocument);
|
|
create_text_node:
|
|
{
|
|
LDOM_BasicNode& aTextNode =
|
|
LDOM_BasicText::Create (aLocType, aTextValue, myDocument);
|
|
aParent -> AppendChild (&aTextNode, aLastChild);
|
|
}
|
|
delete [] aTextStr;
|
|
break;
|
|
case LDOM_XmlReader::XML_EOF:
|
|
myError = "Inexpected end of file";
|
|
isError = Standard_True;
|
|
break;
|
|
default: ;
|
|
}
|
|
if (isError) break;
|
|
}
|
|
return isError;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : startElement
|
|
//purpose : virtual hook on 'StartElement' event for descendant classes
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::startElement ()
|
|
{
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : endElement
|
|
//purpose : virtual hook on 'EndElement' event for descendant classes
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LDOMParser::endElement ()
|
|
{
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : getCurrentElement
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
LDOM_Element LDOMParser::getCurrentElement () const
|
|
{
|
|
return LDOM_Element (myReader -> GetElement(), myDocument);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : getDocument
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
LDOM_Document LDOMParser::getDocument ()
|
|
{
|
|
return myDocument -> Self();
|
|
}
|
|
|