Expressir (“EXPRESS in Ruby”) is a Ruby parser for EXPRESS and a set of Ruby tools for accessing ISO EXPRESS data models.
Expressir consists of 3 parts:
-
Parsers. A parser allows Expressir to read EXPRESS files, including:
-
EXPRESS data modelling language (ISO 10303-11:2007)
-
EXPRESS data modelling language in XML (STEPmod)
-
EXPRESS XML (ISO 10303-28:2007) “Industrial automation systems and integration — Product data representation and exchange — Part 28: Implementation methods: XML representations of EXPRESS schemas and data, using XML schemas”
-
-
Data model. The data model (
lib/expressir/express
) is the Ruby data model that fully represents an EXPRESS data model. -
Converters. A converter transforms the EXPRESS Ruby data model into an interoperable export format, including:
-
EXPRESS data modelling language (ISO 10303-11:2007)
-
Add this line to your application’s Gemfile
:
gem "expressir"
And then execute:
$ bundle install
Or install it yourself as:
$ gem install expressir
This gem ships with a CLI tool. To check what’s available you can simply run
expressir
, by default it will display some usage instructions.
$ expressir
Commands:
expressir benchmark FILE_OR_YAML # Benchmark schema loading performance for a file or list of files from YAML
expressir benchmark-cache FILE_OR_YAML # Benchmark schema loading with caching
expressir clean PATH # Strip remarks and prettify EXPRESS schema at PATH
expressir format PATH # pretty print EXPRESS schema located at PATH
expressir help [COMMAND] # Describe available commands or one specific command
expressir validate *PATH # validate EXPRESS schema located at PATH
expressir version # Expressir Version
The clean
command strips remarks and prettifies EXPRESS schemas. You can
optionally save the result to a file.
# Output to stdout
expressir clean schemas/resources/action_schema/action_schema.exp
# Save to file
expressir clean schemas/resources/action_schema/action_schema.exp --output clean_schema.exp
Expressir includes powerful benchmarking capabilities for measuring schema loading performance. You can benchmark individual files or multiple files listed in a YAML configuration.
# Basic benchmarking
expressir benchmark schemas/resources/action_schema/action_schema.exp
# With detailed output
expressir benchmark schemas/resources/action_schema/action_schema.exp --verbose
# Using benchmark-ips for more detailed statistics
expressir benchmark schemas/resources/action_schema/action_schema.exp --ips
# With specific output format
expressir benchmark schemas/resources/action_schema/action_schema.exp --format json
Create a YAML file with a list of schema paths:
schemas:
- schemas/resources/action_schema/action_schema.exp
- schemas/resources/approval_schema/approval_schema.exp
- schemas/resources/date_time_schema/date_time_schema.exp
Then benchmark all schemas at once:
expressir benchmark schemas.yml --verbose
You can also benchmark schema loading with caching to measure parsing time, cache writing time, and cache reading time:
# Benchmark a single file with caching
expressir benchmark-cache schemas/resources/action_schema/action_schema.exp
# With custom cache location
expressir benchmark-cache schemas/resources/action_schema/action_schema.exp --cache_path /tmp/schema_cache.bin
# Benchmark multiple files from YAML with caching
expressir benchmark-cache schemas.yml --verbose
The benchmark commands support several options:
Option | Description |
---|---|
|
Use benchmark-ips for detailed statistics |
|
Show detailed output |
|
Save benchmark results to file |
|
Output format: json, csv, or default |
|
(benchmark-cache only) Path to store the cache file |
When using the --format json
option, results will be output in JSON format,
making it easy to parse for further analysis or visualization.
Use the from_file
method to parse a single EXPRESS schema file:
# Parse a single file
repository = Expressir::Express::Parser.from_file("path/to/schema.exp")
# With options
repository = Expressir::Express::Parser.from_file(
"path/to/schema.exp",
skip_references: false, # Set to true to skip resolving references
include_source: true, # Set to true to include original source in the model
root_path: "/base/path" # Optional base path for relative paths
)
The from_file
method will raise a SchemaParseFailure
exception if the schema
fails to parse, providing information about the specific file and the parsing
error:
begin
repository = Expressir::Express::Parser.from_file("path/to/schema.exp")
rescue Expressir::Express::Error::SchemaParseFailure => e
puts "Failed to parse schema: #{e.message}"
puts "Filename: #{e.filename}"
puts "Error details: #{e.parse_failure_cause.ascii_tree}"
end
Use the from_files
method to parse multiple EXPRESS schema files:
# Parse multiple files
files = ["schema1.exp", "schema2.exp", "schema3.exp"]
repository = Expressir::Express::Parser.from_files(files)
You can provide a block to track loading progress and handle errors:
files = ["schema1.exp", "schema2.exp", "schema3.exp"]
repository = Expressir::Express::Parser.from_files(files) do |filename, schemas, error|
if error
puts "Error loading #{filename}: #{error.message}"
# Skip the file with an error or take other action
else
puts "Successfully loaded #{schemas.length} schemas from #{filename}"
end
end
You can filter out specific schemas from the repository easily since
Expressir::Model::Repository
implements Enumerable
.
schema_yaml = YAML.load_file('documents/iso-10303-41/schemas.yaml')
schema_paths = schema_yaml['schemas'].map {|x,y| y['path'].gsub("../../", "")}
repo = Expressir::Express::Parser.from_files(schema_paths)
filtered_schemas = ["action_schema", "date_time_schema"]
repo.select do |schema|
filtered_schemas.include?(schema.name)
end.each do |schema|
puts "Schema name: #{schema.name}"
puts "Schema file: #{schema.file}"
puts "Schema version: #{schema.version}"
end
Use to_liquid
method to convert the models of Expressir::Model::*
to liquid
drop models (Expressir::Liquid::*
).
Example:
repo = Expressir::Express::Parser.from_file("path/to/file.exp")
repo_drop = repo.to_liquid
where repo
is an instance of Expressir::Model::Repository
and
repo_drop
is an instance of Expressir::Liquid::RepositoryDrop
.
The Liquid drop models of Expressir::Liquid::*
have the same attributes
(model_attr
) as the models of Expressir::Model::*
.
For example, Expressir::Model::Repository
has the following attributes:
-
schemas
and each Expressir::Model::Declarations::Schema
has the following attributes:
-
file
-
version
-
interfaces
-
constants
-
entities
-
subtype_constraints
-
functions
-
rules
-
procedures
Thus, Expressir::Liquid::Repository
has the same attribute schemas
and Expressir::Liquid::Declarations::SchemaDrop
has same attribute file
.
repo = Expressir::Express::Parser.from_file("path/to/file.exp")
repo_drop = repo.to_liquid
schema = repo_drop.schemas.first
schema.file = "path/to/file.exp"
First, thank you for contributing! We love pull requests from everyone. By participating in this project, you hereby grant Ribose Inc. the right to grant or transfer an unlimited number of non exclusive licenses or sub-licenses to third parties, under the copyright covering the contribution to use the contribution by all means.
Here are a few technical guidelines to follow:
-
Open an issues to discuss a new feature.
-
Write tests to support your new feature.
-
Make sure the entire test suite passes locally and on CI.
-
Open a Pull Request.
-
Squash your commits after receiving feedback.
-
Party!
Expressir provides detailed documentation on various aspects of its functionality:
-
Benchmarking: Learn about Expressir’s built-in capabilities for measuring schema loading performance, particularly useful for large schemas or when optimizing performance.
-
Liquid Integration: Documentation on how to use Expressir models with Liquid templates for flexible document generation.
Expressir is distributed under the BSD 2-clause license.
Note
|
Expressir originally contained some code from the NIST Reeper project but no longer contains them. |
The NIST Reeper license is reproduced below:
This software was funded by NIST and developed by EuroSTEP. Pursuant to title 17 Section 105 of the United States Code this software is not subject to copyright protection and is in the public domain.
We would appreciate acknowledgment if the software is used. Links to non-Federal Government Web sites do not imply NIST endorsement of any particular product, service, organization, company, information provider, or content.