Difficult properties to parse
Opened this issue · 2 comments
andrewisen commented
Some IfcPropertySingleValue that are difficult to parse
'Type',$,IFCLABEL('Table-Night Stand: 24" x 24" x 30"'),$
'URL',$,IFCLABEL('http://www.website.com/anchor#!/800X800-1'),$
'SystemID',$,IFCLABEL('Piping System: KB03R'),$
'TypeDescription',$,IFCTEXT('Circular, smooth,R=D'),$
'AboveGround',$,IFCLOGICAL(.U.),$
'StoreyName',$,IFCTEXT('Level: 02 - Floor'),$
'Diameter',$,IFCPOSITIVELENGTHMEASURE(315.),$
'TypeDescription',$,IFCTEXT('K30, R\X2\00F6\X0\rsk\X2\00E5\X0\l mineralull ytbekl armerad al-folie difft\X2\00E4\X0\t'),$
'Render Appearance Properties',$,IFCTEXT('{2, 15},{39, RPC-16-FXGQ-QK7X-PJ74-6000-ST1L-LVER-AU},{1, 0},{1, 0},{2, 36},{1, 8},{5, Color},{1, 0},{1, 0},{3, 0.8},{3, 0.8},{3, 0.8},{1, 8},{7, BBoxMin},{1, 0},{1, 0},{1, 0},{1, 0},{1, 0},{1, 8},{7, BBoxMax},{1, 0},{1, 0},{1, 0},{1, 0},{1, 0},{2, 11},{9, RPCTypeId},{1, 0},{1, 0},{39, RPC-16-FXGQ-QK7X-PJ74-6000-ST1L-LVER-AU},{1, 6},{14, RPCPlantHeight},{1, 0},{1, 0},{7, 18.0446},{2, 11},{7, keyword},{1, 0},{1, 0},{140, :Geometry:RPC:Golden-chain :Laburnum:Laburnums are very small trees native to southern Europe. The common cultivar in Canada is ''Watereri''.},{2, 11},{8, category},{1, 0},{1, 0},{16, :Trees [General]},{2, 11},{12, LocalizedUID},{1, 0},{1, 0},{13, Golden-chain },{2, 14},{6, Height},{1, 0},{1, 0},{7, 18.0446},{1, 2},{16, Cast Reflections},{1, 0},{1, 0},{1, 0},{1, 2},{12, Cast Shadows},{1, 0},{1, 0},{1, 1},{1, 2},{9, Lock View},{1, 0},{1, 0},{1, 0},{1, 4},{5, ViewC},{1, 0},{1, 0},{1, 0},{2, 11},{11, RPCFilePath},{1, 0},{1, 0},{99, C:\\RevitRender\\Version2015940\\2017\\assetlibrary_base.fbm\\RPCs\\ArchVision_Stills_T5_Golden_Chain.rpc},{2, 11},{20, AdvancedUIDefinition},{1, 0},{1, 0},{0, },{2, 11},{10, AssetLibID},{1, 0},{1, 0},{36, 4D3F6E72-3F99-4203-98E9-AF80B3C7A7A4},{2, 11},{10, BaseSchema},{1, 0},{1, 0},{9, RPCSchema},{2, 11},{12, ExchangeGUID},{1, 0},{1, 0},{0, },{1, 2},{6, Hidden},{1, 0},{1, 0},{1, 0},{1, 4},{11, RPCCategory},{1, 0},{1, 0},{1, 0},{2, 11},{8, RPCImage},{1, 0},{1, 0},{0, },{1, 4},{13, SchemaVersion},{1, 0},{1, 0},{1, 5},{2, 11},{12, UIDefinition},{1, 0},{1, 0},{0, },{2, 11},{6, UIName},{1, 0},{1, 0},{39, RPC-16-FXGQ-QK7X-PJ74-6000-ST1L-LVER-AU},{2, 11},{11, VersionGUID},{1, 0},{1, 0},{9, RPCSchema},{2, 11},{9, assettype},{1, 0},{1, 0},{11, RPCGeometry},{2, 11},{11, description},{1, 0},{1, 0},{0, },{2, 11},{9, localname},{1, 0},{1, 0},{3, RPC},{2, 11},{9, localtype},{1, 0},{1, 0},{3, RPC},{1, 4},{8, revision},{1, 0},{1, 0},{1, 1},{2, 11},{9, thumbnail},{1, 0},{1, 0},{0, },{1, 4},{7, version},{1, 0},{1, 0},{1, 1},{1, 2},{20, RPC_Cast Reflections},{1, 0},{1, 0},{1, 1},{1, 2},{16, RPC_Cast Shadows},{1, 0},{1, 0},{1, 1},{1, 2},{13, RPC_Lock View},{1, 0},{1, 0},{1, 0},{1, 4},{9, RPC_ViewC},{1, 0},{1, 0},{1, 0},{21, assetlibrary_base.fbx},{1, 5},'),$
'2moeq0lkL9rx1tiYe2hZKW',#42,'Pipe Insulation:K30:11937246',$,'Pipe Insulation:K30',#1365555,#1367655,'11937246',.INSULATION.
andrewisen commented
Let's use this as an example:
foo, IFCXXX( YYY ), bar
Also, let's use some JavaScript terminology.
Let's say;
- IFCXXX is a function
- YYY is its parameter
A very simple workaround is to:
- Remove the parameter from the entire string
- Perform the parsing (as normal)
- Parse the parameter as well
- Add back the parameter to the original string
This works surprisingly well.
var myString = "'Description',$,IFCTEXT('_DESCRIPTION_'),$"
var myStringWithNoParameter = "'Description',$,IFCTEXT({PARAMETER}),$"
var myParameter = myString.getParameter()
var myStringAsJSON = myStringWithOutFunction.parse()
var myParameterAsJSON = myParameter.parser()
var myFinalString = myStringAsJSON(/{PARAMETER}/, myParameterAsJSON)
See _parseStepInstanceAttributes for more info.
andrewisen commented
Or, in actual JavaScript
- Prepare the variables
var parsedAttributesString = ""; // This is the string we want to return
/**
* Let's "remove" the GlobalId
*/
var before = ""; // IFC GlobalId
var after = ""; // "Not IFC GlobalId"
- Deal with GlobalId (GUIID)
/**
* In my paser; every object that IS NOT an IfcPropertySingleValue is assumed to have a GlobalId
*/
if (entityName !== "IFCPROPERTYSINGLEVALUE") {
before = attributeString.substr(0, attributeString.indexOf(",")); // Always the first parameter
after = attributeString.substr(attributeString.indexOf(",")); // The rest of the attributes
parsedAttributesString = after;
} else {
parsedAttributesString = attributeString; // The string DOES NOT contain a GlobalId
}
- Add commas to make life easier.
You don't need to write any edge cases for the RegEx
parsedAttributesString = "," + parsedAttributesString + ","; // This will make the parsing a lot easier
- Deal with "functions" and its "parameter"
/**
* Check if the attribute string has a "function"
*/
var hasFunction = false;
var functionParameter = /(IFC[A-Z]+\()(.*)(\)\,)/g.exec(parsedAttributesString);
if (functionParameter) {
hasFunction = true;
// Parse the "parameter"
functionParameter = functionParameter[2]
.replace(/\\/g, "") // Backward slashes
.replace(/\//g, "\\/") // Forward slashes
.replace(/\"/g, '\\"'); // Quotation marks
parsedAttributesString = parsedAttributesString.replace(
/(IFC[A-Z]+\()(.*)(\)\,)/g,
'"$1{PARAM})",'
);
}
- Perform the regular parsing (from a regular string into a JSON object)
// Regular parsing
parsedAttributesString = parsedAttributesString
.replace(/\\/g, "") // Backward slashes
.replace(/\//g, "\\/") // Forward slashes
.replace(/\$/g, '"$"') // Indefinite attributes
.replace(/(^|,)\((#\d+.*?)\)/g, "$1[$2]") // Nested attributes
.replace(/([,\[])(#\d+)+/g, '$1"$2"') // References to other entities (e.g. #123)
.replace(/,(\d+[.]\d*)/g, ",'$1'") // Integers (that are not escaped)
.replace(/'/g, '"'); // Convert all remaining apostrophes to quotes
- Add back the "parameter" (optional)
if (hasFunction) {
parsedAttributesString = parsedAttributesString.replace(
/(IFC[A-Z]+\()(\{PARAM\})(\)\"\,)/g,
"$1" + functionParameter + ')",'
);
}
- Add back the GlobalId (optional)
if (entityName !== "IFCPROPERTYSINGLEVALUE") {
// Add back the GlobalId
parsedAttributesString =
'"' +
before.slice(1, -1) +
'"' +
parsedAttributesString.slice(1, -1); // Remove the added comas
} else {
parsedAttributesString = parsedAttributesString.slice(1, -1); ; // Remove the added comas
}
- Return the parsed string (i.e. a JSON object)
return JSON.parse("[" + parsedAttributesString + "]");