//purpose :
//=======================================================================
-Standard_Boolean LDOMParser::parse (istream& anInput)
+Standard_Boolean LDOMParser::parse (istream& anInput,
+ const Standard_Boolean theTagPerStep,
+ const Standard_Boolean theWithoutRoot)
{
// Open the DOM Document
myDocument = new LDOM_MemManager (20000);
// Create the Reader instance
if (myReader) delete myReader;
- myReader = new LDOM_XmlReader (myDocument, myError);
+ myReader = new LDOM_XmlReader (myDocument, myError, theTagPerStep);
// Parse
- return ParseDocument (anInput);
+ return ParseDocument (anInput, theWithoutRoot);
}
//=======================================================================
//purpose : parse the whole document (abstracted from the XML source)
//=======================================================================
-Standard_Boolean LDOMParser::ParseDocument (istream& theIStream)
+Standard_Boolean LDOMParser::ParseDocument (istream& theIStream, const Standard_Boolean theWithoutRoot)
{
Standard_Boolean isError = Standard_False;
Standard_Boolean isElement = Standard_False;
Standard_Boolean isDoctype = Standard_False;
+ Standard_Boolean isInsertFictRootElement = Standard_False;
+
for(;;) {
- LDOM_XmlReader::RecordType aType = ReadRecord (*myReader, theIStream, myCurrentData);
+ LDOM_XmlReader::RecordType aType = (theWithoutRoot && !isInsertFictRootElement ?
+ LDOM_XmlReader::XML_START_ELEMENT :
+ ReadRecord (*myReader, theIStream, myCurrentData));
switch (aType) {
case LDOM_XmlReader::XML_HEADER:
if (isDoctype || isElement) {
case LDOM_XmlReader::XML_START_ELEMENT:
if (isElement == Standard_False) {
isElement = Standard_True;
- myDocument -> myRootElement = &myReader -> GetElement ();
+
+ if (theWithoutRoot && !isInsertFictRootElement)
+ {
+ isInsertFictRootElement = Standard_True;
+
+ // create fiction root element
+ TCollection_AsciiString aFicName ("document");
+ myReader->CreateElement (aFicName.ToCString(), aFicName.Length());
+ }
+
+ myDocument->myRootElement = &myReader->GetElement();
+
if (startElement()) {
isError = Standard_True;
myError = "User abort at startElement()";
// Returns True if error occurred, then GetError() can be called
Standard_EXPORT Standard_Boolean
- parse (istream& anInput);
+ parse (istream& anInput,
+ const Standard_Boolean theTagPerStep = Standard_False,
+ const Standard_Boolean theWithoutRoot = Standard_False);
// Parse a C++ stream
+ // theTagPerStep - if true - extract characters from anInput until '>'
+ // extracted character and parse only these characters.
+ // if false - extract until eof
+ // theWithoutRoot - if true - create fictive "document" element before parsing
+ // and consider that document start element has been already read
+ // - if false - parse a document as usual (parse header, document tag and etc)
// Returns True if error occurred, then GetError() can be called
Standard_EXPORT const TCollection_AsciiString&
private:
// ---------- PRIVATE METHODS ----------
- Standard_Boolean ParseDocument (Standard_IStream& theIStream);
+ Standard_Boolean ParseDocument (Standard_IStream& theIStream, const Standard_Boolean theWithoutRoot = Standard_False);
Standard_Boolean ParseElement (Standard_IStream& theIStream);
LDOM_XmlReader::LDOM_XmlReader (
const Handle(LDOM_MemManager)& theDocument,
- TCollection_AsciiString& theErrorString)
+ TCollection_AsciiString& theErrorString,
+ const Standard_Boolean theTagPerStep)
: myEOF (Standard_False),
myError (theErrorString),
myDocument (theDocument),
myElement (NULL),
myLastChild(NULL),
myPtr (&myBuffer[0]),
- myEndPtr (&myBuffer[0])
+ myEndPtr (&myBuffer[0]),
+ myTagPerStep (theTagPerStep)
{
}
const char * aStartData = NULL, * aNameEnd = NULL, * aPtr;
LDOMBasicString anAttrName, anAttrValue;
char anAttDelimiter = '\0';
+ Standard_Boolean aHasRead = Standard_False;
for(;;) {
// Check if the current file buffer is exhausted
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// There should always be some bytes available in the buffer for analysis
Standard_Integer aBytesRest = (Standard_Integer)(myEndPtr - myPtr);
- if (aBytesRest < XML_MIN_BUFFER) {
- if (myEOF == Standard_True) {
+ if (aBytesRest < XML_MIN_BUFFER)
+ {
+ if (myEOF == Standard_True)
+ {
if (aBytesRest <= 0)
break; // END of processing
- } else {
+ }
+ else if (myTagPerStep && aHasRead)
+ {
+ }
+ else
+ {
// If we are reading some data, save the beginning and preserve the state
if (aStartData /* && aState != STATE_WAITING */) {
if (myPtr > aStartData)
// Read the full buffer and reset start and end buffer pointers
myPtr = &myBuffer[0];
Standard_Size aNBytes;
- theIStream.read (&myBuffer[aBytesRest],
- XML_BUFFER_SIZE - aBytesRest);
- aNBytes = (Standard_Size)theIStream.gcount();
+
+ if (myTagPerStep)
+ {
+ theIStream.getline (&myBuffer[aBytesRest], XML_BUFFER_SIZE - aBytesRest, '>');
+ aHasRead = Standard_True;
+ }
+ else
+ {
+ theIStream.read (&myBuffer[aBytesRest], XML_BUFFER_SIZE - aBytesRest);
+ }
+ aNBytes = (Standard_Size)theIStream.gcount();
+
if (aNBytes == 0)
+ {
myEOF = Standard_True; // END-OF-FILE
+ }
+ else if (myTagPerStep)
+ {
+ // replace \0 (being inserted by getline method) with >
+ myBuffer[aBytesRest + aNBytes - 1] = '>';
+ }
myEndPtr = &myBuffer[aBytesRest + aNBytes];
myBuffer[aBytesRest + aNBytes] = '\0';
}
return aResult;
}
+//=======================================================================
+//function : CreateElement
+//purpose :
+//=======================================================================
+void LDOM_XmlReader::CreateElement( const char *theName, const Standard_Integer theLen )
+{
+ myElement = &LDOM_BasicElement::Create (theName, theLen, myDocument);
+}
+
//=======================================================================
//function : getInteger
//purpose : Try to initialize theValue as Integer; return False on success
// ---------- PUBLIC METHODS ----------
LDOM_XmlReader (const Handle(LDOM_MemManager)& aDocument,
- TCollection_AsciiString& anErrorString);
+ TCollection_AsciiString& anErrorString,
+ const Standard_Boolean theTagPerStep = Standard_False);
// Constructor - takes a file descriptor for input
// Constructor - takes an istream for input
LDOM_BasicElement& GetElement () const { return * myElement; }
// get the last element retrieved from the stream
+ void CreateElement (const char *theName, const Standard_Integer theLen);
+
static Standard_Boolean getInteger (LDOMBasicString& theValue,
const char * theStart,
const char * theEnd);
const char * myPtr;
const char * myEndPtr;
char myBuffer [XML_BUFFER_SIZE+4];
+ Standard_Boolean myTagPerStep;
};
#endif
{
TCollection_AsciiString aReadMagicNumber;
+ // read magic number from the file
if (theIStream.good())
{
- streampos aDocumentPos = theIStream.tellg();
-
- // read magic number from the file
aReadMagicNumber = Storage_BaseDriver::ReadMagicNumber (theIStream);
-
- if (!theIStream.good())
- {
- theIStream.clear();
- }
-
- theIStream.seekg(aDocumentPos);
}
if(aReadMagicNumber == FSD_CmpFile::MagicNumber())
theBaseDriver = new FSD_BinaryFile;
return PCDM_TOFD_File;
}
+ else if (aReadMagicNumber.Search ("<?xml") != -1)
+ {
+ // skip xml declaration
+ char aChar = ' ';
+ while (theIStream.good() && !theIStream.eof() && aChar != '>')
+ {
+ theIStream.get(aChar);
+ }
+
+ return PCDM_TOFD_XmlFile;
+ }
theBaseDriver = NULL;
return PCDM_TOFD_Unknown;
TCollection_ExtendedString aFormat;
Storage_BaseDriver* aFileDriver;
- if (PCDM::FileDriverType (theIStream, aFileDriver) == PCDM_TOFD_Unknown)
+ if (PCDM::FileDriverType (theIStream, aFileDriver) == PCDM_TOFD_XmlFile)
{
return ::TryXmlDriverType (theIStream);
}
-
- // the stream starts with a magic number, FileDriverType has read
- // them already but returned the stream pos to initial state,
- // thus we should read them before reading of info section
- aFileDriver->ReadMagicNumber(theIStream);
+
aFileDriver->ReadCompleteInfo (theIStream, theData);
if (theIStream.good())
{
- streampos aDocumentPos = theIStream.tellg();
-
// Parse the file; if there is no error or an error appears before retrieval
// of the DocumentElement, the XML format cannot be defined
- if (aParser.parse (theIStream))
+ if (aParser.parse (theIStream, Standard_True))
{
LDOM_Element anElement = aParser.GetElement();
if (anElement.getTagName().equals (LDOMString(aDocumentElementName)))
theFormat = anElement.getAttribute ("format");
}
-
- if (!theIStream.good())
- {
- theIStream.clear();
- }
-
- theIStream.seekg(aDocumentPos);
}
return theFormat;
{
PCDM_TOFD_File,
PCDM_TOFD_CmpFile,
+PCDM_TOFD_XmlFile,
PCDM_TOFD_Unknown
};
// 1. Read DOM_Document from file
LDOMParser aParser;
- if (aParser.parse(theIStream))
+ // if myFileName is not empty, "document" tag is required to be read
+ // from the received document
+ Standard_Boolean aWithoutRoot = myFileName.IsEmpty();
+
+ if (aParser.parse(theIStream, Standard_False, aWithoutRoot))
{
TCollection_AsciiString aData;
cout << aParser.GetError(aData) << ": " << aData << endl;