0031340: LDOM fails to read XML file starting with BOM
[occt.git] / src / LDOM / LDOMParser.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 74a7195..341d902
@@ -1,8 +1,19 @@
-// File:      LDOMParser.cxx
-// Created:   20.07.01 14:58:24
-// Author:    Alexander GRIGORIEV
-// Copyright: OpenCascade 2001
-// History:   AGV 060302: Input from istream
+// Created on: 2001-07-20
+// 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.
+
+//AGV 060302: Input from std::istream
 //            AGV 130302: Return error if there are data after the root element
 
 //#define LDOM_PARSER_TRACE
 #include <LDOM_XmlReader.hxx>
 #include <LDOM_BasicText.hxx>
 #include <LDOM_CharReference.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <OSD_OpenFile.hxx>
 
 #include <fcntl.h>
-#ifdef WNT
+#ifdef _MSC_VER
 #include <io.h>
 #else
 #include <unistd.h>
@@ -41,17 +54,18 @@ static
 inline
 #endif
         LDOM_XmlReader::RecordType ReadRecord (LDOM_XmlReader&  aReader,
+                                               Standard_IStream& theIStream,
                                                LDOM_OSStream&   aData)
 {
 #ifdef LDOM_PARSER_TRACE
   static aCounter = 0;
   ++ aCounter;
 #endif
-  const LDOM_XmlReader::RecordType aType = aReader.ReadRecord (aData);
+  const LDOM_XmlReader::RecordType aType = aReader.ReadRecord (theIStream, aData);
 #ifdef LDOM_PARSER_TRACE
   static FILE * ff = NULL;
   TCollection_AsciiString aTraceFileName;
-#ifdef WNT
+#ifdef _WIN32
   aTraceFileName = TCollection_AsciiString (getenv("TEMP")) + "\\ldom.trace";
 #else
   aTraceFileName = "/tmp/ldom.trace";
@@ -92,12 +106,26 @@ const TCollection_AsciiString& LDOMParser::GetError
   return myError;
 }
 
+//=======================================================================
+//function : GetBOM
+//purpose  : Returns the byte order mask defined at the start of a stream
+//=======================================================================
+
+LDOM_OSStream::BOMType LDOMParser::GetBOM() const
+{
+  if (myReader)
+    return myReader->GetBOM();
+  return LDOM_OSStream::BOM_UNDEFINED;
+}
+
 //=======================================================================
 //function : parse
 //purpose  :
 //=======================================================================
 
-Standard_Boolean LDOMParser::parse (istream& anInput)
+Standard_Boolean LDOMParser::parse (std::istream& anInput,
+                                    const Standard_Boolean theTagPerStep,
+                                    const Standard_Boolean theWithoutRoot)
 {
   // Open the DOM Document
   myDocument = new LDOM_MemManager (20000);
@@ -105,10 +133,10 @@ Standard_Boolean LDOMParser::parse (istream& anInput)
 
   // Create the Reader instance
   if (myReader) delete myReader;
-  myReader = new LDOM_XmlReader (anInput, myDocument, myError);
+  myReader = new LDOM_XmlReader (myDocument, myError, theTagPerStep);
 
   // Parse
-  return ParseDocument();
+  return ParseDocument (anInput, theWithoutRoot);
 }
 
 //=======================================================================
@@ -118,25 +146,18 @@ Standard_Boolean LDOMParser::parse (istream& anInput)
 
 Standard_Boolean LDOMParser::parse (const char * const aFileName)
 {
-  // Open the DOM Document
-  myDocument = new LDOM_MemManager (20000);
-  myError.Clear ();
+  std::ifstream aFileStream;
+  OSD_OpenStream (aFileStream, aFileName, std::ios::in);
 
-  // Open the file
-  int aFile = open (aFileName, O_RDONLY);
-  if (aFile < 0) {
+  if (aFileStream.good())
+  {
+    return parse (aFileStream);
+  }
+  else
+  {
     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;
 }
 
 //=======================================================================
@@ -144,15 +165,18 @@ Standard_Boolean LDOMParser::parse (const char * const aFileName)
 //purpose  : parse the whole document (abstracted from the XML source)
 //=======================================================================
 
-Standard_Boolean LDOMParser::ParseDocument ()
+Standard_Boolean LDOMParser::ParseDocument (std::istream& theIStream, const Standard_Boolean theWithoutRoot)
 {
   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);
+  Standard_Boolean      isInsertFictRootElement = Standard_False;
+
+  for(;;) {
+    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) {
@@ -160,7 +184,6 @@ Standard_Boolean LDOMParser::ParseDocument ()
         isError = Standard_True;
         break;
       }
-      isHeader = Standard_True;
       continue;
     case LDOM_XmlReader::XML_DOCTYPE:
       if (isElement) {
@@ -169,6 +192,7 @@ Standard_Boolean LDOMParser::ParseDocument ()
         break;
       }
       isDoctype = Standard_True;
+      continue;
     case LDOM_XmlReader::XML_COMMENT:
       continue;
     case LDOM_XmlReader::XML_FULL_ELEMENT:
@@ -187,26 +211,42 @@ Standard_Boolean LDOMParser::ParseDocument ()
         }
         continue;
       }
+      isError = Standard_True;
+      myError = "Expected comment or end-of-file";
+      break;
     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()";
           break;
         }
-        isError = ParseElement ();
+        isError = ParseElement (theIStream);
         if (isError) break;
         continue;
       }
       isError = Standard_True;
       myError = "Expected comment or end-of-file";
+      break;
     case LDOM_XmlReader::XML_END_ELEMENT:
       if (endElement()) {
         isError = Standard_True;
         myError = "User abort at endElement()";
       }
+      break;
     case LDOM_XmlReader::XML_EOF:
       break;
     case LDOM_XmlReader::XML_UNKNOWN:
@@ -226,16 +266,16 @@ Standard_Boolean LDOMParser::ParseDocument ()
 //purpose  : parse one element, given the type of its XML presentation
 //=======================================================================
 
-Standard_Boolean LDOMParser::ParseElement ()
+Standard_Boolean LDOMParser::ParseElement (Standard_IStream& theIStream)
 {
   Standard_Boolean  isError = Standard_False;
   const LDOM_BasicElement * aParent = &myReader->GetElement();
   const LDOM_BasicNode    * aLastChild = NULL;
-  while (1) {
+  for(;;) {
     LDOM_Node::NodeType aLocType;
     LDOMBasicString     aTextValue;
     char *aTextStr;
-    LDOM_XmlReader::RecordType aType = ReadRecord (* myReader, myCurrentData);
+    LDOM_XmlReader::RecordType aType = ReadRecord (* myReader, theIStream, myCurrentData);
     switch (aType) {
     case LDOM_XmlReader::XML_UNKNOWN:
       isError = Standard_True;
@@ -260,7 +300,7 @@ Standard_Boolean LDOMParser::ParseElement ()
         myError = "User abort at startElement()";
         break;
       }
-      isError = ParseElement ();
+      isError = ParseElement (theIStream);
       break;
     case LDOM_XmlReader::XML_END_ELEMENT:
       {