internal IfcFileHeader Read(IfcPersistedInstanceCache instanceCache, XbimEntityCursor entityTable, XmlReader input) { // Read until end of file idMap = new Dictionary <string, int>(); lastId = 0; _entitiesParsed = 0; bool foundHeader = false; IfcFileHeader header = new IfcFileHeader(IfcFileHeader.HeaderCreationMode.LeaveEmpty); string headerId = ""; while (_currentNode == null && input.Read()) //read through to UOS { switch (input.NodeType) { case XmlNodeType.Element: if (string.Compare(input.LocalName, "uos", true) == 0) { _currentNode = new XmlUosCollection(); } else if (string.Compare(input.LocalName, "iso_10303_28", true) == 0) { foundHeader = true; if (!string.IsNullOrWhiteSpace(input.Prefix)) { _expressNamespace = input.Prefix; _cTypeAttribute = _expressNamespace + ":cType"; _posAttribute = _expressNamespace + ":pos"; _expressNamespace += ":"; } else { _cTypeAttribute = "cType"; _posAttribute = "pos"; } //correct the values if the namespace is defined correctly while (input.MoveToNextAttribute()) { if (input.Value == "urn:oid:1.0.10303.28.2.1.1" || input.Value == "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common") { _expressNamespace = input.LocalName; _cTypeAttribute = _expressNamespace + ":cType"; _posAttribute = _expressNamespace + ":pos"; _expressNamespace += ":"; break; } } } else { headerId = input.LocalName.ToLower(); } break; case XmlNodeType.Text: switch (headerId) { case "name": header.FileName.Name = input.Value; break; case "time_stamp": header.FileName.TimeStamp = input.Value; break; case "author": header.FileName.AuthorName.Add(input.Value); break; case "organization": header.FileName.Organization.Add(input.Value); break; case "preprocessor_version": header.FileName.PreprocessorVersion = input.Value; break; case "originating_system": header.FileName.OriginatingSystem = input.Value; break; case "authorization": header.FileName.AuthorizationName = input.Value; break; case "documentation": header.FileDescription.Description.Add(input.Value); break; default: break; } break; default: break; } } if (!foundHeader) { throw new Exception("Invalid XML format, iso_10303_28 tag not found"); } XmlNodeType prevInputType = XmlNodeType.None; string prevInputName = ""; // set counter for start of every element that is not empty, and reduce it on every end of that element try { using (var transaction = entityTable.BeginLazyTransaction()) { // this will create id of each element Dictionary <string, int> ids = new Dictionary <string, int>(); while (input.Read()) { switch (input.NodeType) { case XmlNodeType.Element: StartElement(instanceCache, input, entityTable, transaction); break; case XmlNodeType.EndElement: IPersistIfcEntity toWrite; //if toWrite has a value we have completed an Ifc Entity EndElement(input, prevInputType, prevInputName, out toWrite); if (toWrite != null) { _entitiesParsed++; //now write the entity to the database entityTable.AddEntity(toWrite); if (_entitiesParsed % _transactionBatchSize == (_transactionBatchSize - 1)) { transaction.Commit(); transaction.Begin(); } } break; case XmlNodeType.Whitespace: SetValue(input, prevInputType, prevInputName); break; case XmlNodeType.Text: SetValue(input, prevInputType, prevInputName); break; default: break; } prevInputType = input.NodeType; prevInputName = input.LocalName; } transaction.Commit(); } } catch (Exception e) { throw new Exception(String.Format("Error reading XML, Line={0}, Position={1}, Tag='{2}'", ((IXmlLineInfo)input).LineNumber, ((IXmlLineInfo)input).LinePosition, input.LocalName), e); } return(header); }
private void StartElement(IfcPersistedInstanceCache cache, XmlReader input, XbimEntityCursor entityTable, XbimLazyDBTransaction transaction) { string elementName = input.LocalName; bool isRefType; int? id = GetId(input, out isRefType); IfcType ifcType; IfcParserType parserType; IfcMetaProperty prop; int propIndex; if (id.HasValue && IsIfcEntity(elementName, out ifcType)) //we have an element which is an Ifc Entity { IPersistIfcEntity ent; if (!cache.Contains(id.Value)) { // not been declared in a ref yet // model.New creates an instance uisng type and id ent = cache.CreateNew(ifcType.Type, id.Value); } else { ent = cache.GetInstance(id.Value, false, true); } XmlEntity xmlEnt = new XmlEntity(_currentNode, ent); //if we have a completely empty element that is not a ref we need to make sure it is written to the database as EndElement will not be called if (input.IsEmptyElement && !isRefType) { _entitiesParsed++; //now write the entity to the database entityTable.AddEntity(xmlEnt.Entity); if (_entitiesParsed % _transactionBatchSize == (_transactionBatchSize - 1)) { transaction.Commit(); transaction.Begin(); } } string pos = input.GetAttribute(_posAttribute); if (string.IsNullOrEmpty(pos)) { pos = input.GetAttribute("pos"); //try without namespace } if (!string.IsNullOrEmpty(pos)) { xmlEnt.Position = Convert.ToInt32(pos); } if (!input.IsEmptyElement) { // add the entity to its parent if its parent is a list //if (!(_currentNode is XmlUosCollection) && _currentNode is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection)) // ((XmlCollectionProperty)_currentNode).Entities.Add(xmlEnt); _currentNode = xmlEnt; } else if (_currentNode is XmlProperty) { // if it is a ref then it will be empty element and wont have an end tag // so nither SetValue nor EndElement will be called, so set the value of ref here e.g. #3 ((XmlProperty)(_currentNode)).SetValue(ent); } else if (!(_currentNode is XmlUosCollection) && _currentNode is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection)) { ((XmlCollectionProperty)_currentNode).Entities.Add(xmlEnt); } } else if (input.IsEmptyElement) { if (IsIfcProperty(elementName, out propIndex, out prop)) { XmlProperty node = new XmlProperty(_currentNode, prop.PropertyInfo, propIndex);; PropertyValue propVal = new PropertyValue(); Type t = node.Property.PropertyType; if (!typeof(ExpressEnumerable).IsAssignableFrom(t)) // if its a empty collection then dont do anything { if (t != null && t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable <>))) { t = Nullable.GetUnderlyingType(t); } ExpressType et = null; if (t != null && typeof(ExpressType).IsAssignableFrom(t)) { et = (ExpressType)(Activator.CreateInstance(t)); } IfcParserType pt; if (et != null) { pt = primitives[et.UnderlyingSystemType.Name]; } else { if (t.IsEnum) { pt = IfcParserType.Enum; } else { pt = primitives[t.Name]; } } if (pt.ToString().ToLower() == "string") { propVal.Init("'" + input.Value + "'", pt); } else { if (pt.ToString().ToLower() == "boolean") { propVal.Init(Convert.ToBoolean(input.Value) ? ".T." : ".F", pt); } else { propVal.Init(input.Value, pt); } } ((XmlEntity)node.Parent).Entity.IfcParse(node.PropertyIndex - 1, propVal); } } else if (IsIfcType(elementName, out ifcType)) { IPersistIfc ent; object[] param = new object[1]; param[0] = ""; // empty element ent = (IPersistIfc)Activator.CreateInstance(ifcType.Type, param); ((XmlProperty)_currentNode).SetValue(ent); } return; } else if (!id.HasValue && IsIfcProperty(elementName, out propIndex, out prop)) //we have an element which is a property { string cType = input.GetAttribute(_cTypeAttribute); if (string.IsNullOrEmpty(cType)) { cType = input.GetAttribute("cType"); //in case namespace omitted } if (IsCollection(prop)) //the property is a collection { XmlCollectionProperty xmlColl = new XmlCollectionProperty(_currentNode, prop.PropertyInfo, propIndex); switch (cType) { case "list": xmlColl.CType = CollectionType.List; break; case "list-unique": xmlColl.CType = CollectionType.ListUnique; break; case "set": xmlColl.CType = CollectionType.Set; break; default: xmlColl.CType = CollectionType.List; break; } _currentNode = xmlColl; } else //it is a simple value property; { // its parent can be a collection, if yes then this property needs to be added to parent XmlNode n = new XmlProperty(_currentNode, prop.PropertyInfo, propIndex); if (_currentNode is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection)) { ((XmlCollectionProperty)_currentNode).Entities.Add(n); } if (!input.IsEmptyElement) { _currentNode = n; } } } else if (!id.HasValue && IsIfcType(elementName, out ifcType)) // we have an Ifc ExpressType { // its parent can be a collection, if yes then this property needs to be added to parent XmlNode n = new XmlExpressType(_currentNode, ifcType.Type); if (_currentNode is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection)) { ((XmlCollectionProperty)_currentNode).Entities.Add(n); } if (!input.IsEmptyElement) { _currentNode = n; } } else if (!id.HasValue && IsPrimitiveType(elementName, out parserType)) // we have an basic type i.e. double, bool etc { // its parent can be a collection, if yes then this property needs to be added to parent XmlNode n = new XmlBasicType(_currentNode, parserType); if (_currentNode is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection)) { ((XmlCollectionProperty)_currentNode).Entities.Add(n); } if (!input.IsEmptyElement) { _currentNode = n; } } else { throw new Exception("Illegal XML element tag"); } }