Skip to content

Latest commit

 

History

History
504 lines (426 loc) · 50.7 KB

README.md

File metadata and controls

504 lines (426 loc) · 50.7 KB

CIMTool-Builders-Library

image
[GitHub Repo]

This is the official UCAIug repository for custom CIMTool XSLT builders and is provided as a public space to create, collaborate and contribute back builders for the benefit of the CIMTool community at large. This library of builders can be used in CIMTool to generate various types of target artifacts from a CIMTool profile definition.

Would you like a custom builder that generates C/C++ objects from your CIMTool profiles? Perhaps you've wished there was a builder to create Apache Avro schemas for data serialization or one that would automatically generate a Google Protocol Buffers .proto file? You can now with CIMTool's custom builder import feature.

Included in this library is the base set of XSLT transforms that come shipped with CIMTool. These have been included to serve as examples or starting points that can be either extended or used as working examples when creating new XSLT builders.

Feel free to initiate a discussion around a new idea for a custom builder or to post a question on the discussions board. Please contribute new builders to this library using the submission process outlined towards the end of this page.

Current Library of Builders

image

Builders Shipped with CIMTool:

XSLT Builder Output Type Description
xsd.xsl XSD schema The xsd.xsl builder generates an XSD schema that is compliant with the IEC 62361-100:2016 (CIM Profiles to XML Schema Mapping) standard. Additionally, these schemas are compatible with the IEC 61968-100:2013 (Implementation Profiles) standard used for enterprise integration.
xsd-part100-ed2.xsl XSD schema This builder is similar to the xsd.xsl builder above in that it also generates an XSD schema that is compliant with IEC 62361-100:2016. However, these generated schemas are uniquely compatible with the new IEC 61968-100:2022 published standard which is not backwards compatible with IEC 61968-100:2013.
legacy-rdfs.xsl RDFS schema The legacy-rdfs.xsl builder generates an early RDFS schema format used prior to that officially defined within the IEC 61970-501:2006 published standard.
legacy-rdfs-augmented.xsl RDFS schema The legacy-rdfs-augmented.xsl builder generates RDFS schema in primary alignment with that defined within the IEC 61970-501:2006 published standard.
rdfs-2020.xsl RDFS schema This rdfs-2020.xsl builder generates RDFS2020 compliant schemas that reflect that latest de facto agreements on extensions post IEC 61970-501:2006.
jpa.xsl Java source file The jpa.xsl builder generates a Java source file (*.java) containing JPA classes compatible with JPA 2.2 and earlier. The defined JPA classes can be utilized in Java applications for persisting profiles to a database.
scala.xsl Scala source file The scala.xsl builder produces a Scala source file (*.scala) that defines a vocabulary for a profile definition. These source files contain Scala classes/objects representative of those in the profile and may be used in applications implemented in the Scala programming language.
sql.xsl SQL DDL file The sql.xsl builder generates an ANSI SQL-compliant DDL (Data Definition Language) script (*.sql) that can be used to create the database tables and fields corresponding to the classes and attributes represented in a profile.
profile-doc-rtf.xsl Microsoft Word file The profile-doc-rtf.xsl builder produces a Microsoft Word compatible RTF (Rich Text Format) document that contains the complete documentation for all classes, attributes and associations defined in a profile.
html.xsl HTML file The html.xsl builder generates a standalone HTML file containing the complete documentation for all classes, attributes and associations defined in a profile.
json-schema-draft-07.xsl JSON schema The json-schema-draft-07.xsl builder generates a JSON schema compliant with the draft IEC 62361-104 standard (CIM Profiles to JSON schema Mapping). The version of the JSON schema specification that the schema conforms to is draft-07.
json-schema-draft-2020-12.xsl JSON schema The json-schema-draft-2020-12.xsl builder generates a JSON schema compliant with the draft IEC 62361-104 standard (CIM Profiles to JSON schema Mapping). The version of the JSON schema specification that the schema conforms to is draft-2020-12.
cimantic-graphs.xsl Python Source Code The cimantic-graphs.xsl builder produces a specialized python dataclass schema to be used as input into the CIMantic Graphs open source library for creating, parsing, and editing CIM power system models using in-memory knowledge graphs.
cimantic-graphs-init.xsl Python Source Code This builder is intended to be used in conjunction with the cimantic-graphs.xsl builder and is responsible for generating the python __init__.py file required for library imports to work correctly.
puml-t2b.xsl PlantUML class diagram The puml-t2b.xsl builder produces a PlantUML class diagram representing the profile (for an RDFS schema) that this builder is executed on. The layout of the diagram is top-to-bottom (i.e. t2b).
puml-l2r.xsl PlantUML class diagram The puml-l2r.xsl builder produces a PlantUML class diagram representing the profile (for an RDFS schema) that this builder is executed on. The layout of the diagram is left-to-right (i.e. l2r).

Community Developed Builders:

XSLT Builder Output Type Description
json-schema-draft-07-jsonschema2pojo.xsl Specialized JSON schema The json-schema-draft-07-jsonschema2pojo.xsl builder produces a specialized JSON schema to be used as input into the jsonschema2pojo open source Maven or Gradle build plugins to generate annotated Java classes for data-binding with Jackson 2.x or Gson. This custom builder was derived from the json-schema-draft-07.xsl builder and is intended to serve as a companion builder to it.
json-schema-draft-2020-12-jsonschema2pojo.xsl Specialized JSON schema The json-schema-draft-2020-12-jsonschema2pojo.xsl builder produces a specialized JSON schema to be used as input into the jsonschema2pojo open source Maven or Gradle build plugins to generate annotated Java classes for data-binding with Jackson 2.x or Gson. This custom builder was derived from the json-schema-draft-2020-12.xsl builder and is intended to serve as a companion builder to it.

Background

CIMTool ships with a variety of different types of builders that generate artifacts based on a profile. Examples of existing builders include those that generate XSD schemas, JPA Java source code, RDBMS DDL scripts, RDFS profiles, and RTF Word docs among others.

A subcategory of builders supported by CIMTool are those that are based on XSLT transforms. In the below screenshot the builders that are selected are those that generate target files using XSLT transforms (click the image to enlarge):

image

Starting with the CIMTool.1.10.0.RC1 release, the ability to import and configure custom user-defined XSLT transforms and have them automatically added to the list of builders was introduced. This new feature opened up a wide range of possibilities for end users to more easily extend the builder capabilities beyond that shipped with the product. No longer do you need to know Eclipse plugin development.

CIMTool's internal XSLT processor was originally the Apache Xalan project that shipped as part of the Java JDK/JRE. Xalan, however, is a W3C XSLT 1.0 compliant XSLT processor. To support the much richer feature sets defined in the XSLT 2.0 and XSLT 3.0 specifications the XSLT processing engine was replaced by Saxon HE 10.8 in the CIMTool.1.10.0 production release.

The screenshots below illustrate how to access the new import and maintenance screens (click on the images to present a larger view):

From the "Import" wizards screen... ...Launch the "Import XSLT Transform Builder" screen
image image
From the "Profile Summary" tab... ...Launch the "Manage XSLT Transform Builders" screen
image image

How XSLT Builders Work

As a working example, the screenshot below illustrates a CIMTool profile named GetUsagePointGroups. The profile is represented as a web ontology language file and appears in the CIMTool project as the GetUsagePointGroups.owl bordered in blue. An .owl file is a public standalone artifact that can be imported or copied into other CIMTool projects.

What is not well known is that CIMTool has an alternate internal representation for a profile that is used specifically by XSLT builders. This internal representation is an XML format structured in such a manner so as to support straightforward and efficient XSLT transformations into any target output. This internal representation is exposed and available for viewing using the XML builder bordered in red in the screenshot.

image


The file generated by the XML builder appears below. Noteworthy observations include:

  • the namespace xmlns:m="http://ucaiug.org//GetUsagePointGroups#" of the profile is declared on the outermost <Catalog> XML element.
  • the <Root> XML elements correspond to all classes declared as concrete in the profile i.e. those represented by the image icon and bordered in green in the above screenshot.
  • the <ComplexType> XML elements correspond to all non-concrete classes declared in the profile i.e. those represented by the image icon.
  • a class's attributes and associations are defined by the <Simple> or <Instance> XML elements respectively.
  • for primitive typed attributes (e.g. string, float, etc.) an xstype XSD attribute is specified with a corresponding value from the set of W3C XSD primitive datatypes.
  • the comments on class and attribute defined in the profile are included in the <Comment> XML elements.
  • minimum and maximum cardinality is declared via the minOccurs and maxOccurs attributes in each of the XML elements.

The significance of this internal representation is that it serves as the input into any XSLT builder(s) enabled for a profile. The XML builder itself is made available only so end users can view the internal representation. It does not need to be checked for XSLT builders to function.

<?xml version="1.0" encoding="UTF-8"?>
<Catalog xmlns="http://langdale.com.au/2005/Message#"
         xmlns:m="http://ucaiug.org/GetUsagePointGroups#"
         ontologyURI="http://.ch/TC57/CIM100"
         baseURI="http://ucaiug.org/GetUsagePointGroups#"
         name="GetUsagePointGroups">
   <Package name="Base" basePackage="http://iec.ch/TC57/CIM100#Package_Base">
      <Comment>This package models configuration of ICCP required for bilateral exchanges.</Comment>
      <ParentPackage name="IEC61970"
                     basePackage="http://iec.ch/TC57/CIM100#Package_IEC61970"/>
   </Package>
   <Package name="Core" basePackage="http://iec.ch/TC57/CIM100#Package_Core">
      <Comment>Contains the core PowerSystemResource and ConductingEquipment entities shared by all applications plus common collections of those entities. Not all applications require all the Core entities.  This package does not depend on any other package except the Domain package, but most of the other packages have associations and generalizations that depend on it.</Comment>
      <ParentPackage name="Base" basePackage="http://iec.ch/TC57/CIM100#Package_Base"/>
   </Package>
   <Package name="IEC61968"
            basePackage="http://iec.ch/TC57/CIM100#Package_IEC61968">
      <Comment>The IEC 61968 subpackages of the CIM are developed, standardized and maintained by the UCA community including its working groups and task forces.</Comment>
      <Comment>Currently, normative parts of the model support the needs of information exchange defined in IEC 61968-3, IEC 61968-4, IEC 61968-5, IEC 61968-6, IEC 61968-8, IEC 61968-9 and in IEC 61968-13.</Comment>
      <ParentPackage name="TC57CIM" basePackage="http://iec.ch/TC57/CIM100#Package_TC57CIM"/>
   </Package>
   <Package name="IEC61970"
            basePackage="http://iec.ch/TC57/CIM100#Package_IEC61970">
      <Comment>Top package for IEC 61970.</Comment>
      <ParentPackage name="TC57CIM" basePackage="http://iec.ch/TC57/CIM100#Package_TC57CIM"/>
   </Package>
   <Package name="Metering"
            basePackage="http://iec.ch/TC57/CIM100#Package_Metering">
      <Comment>This package contains the core information classes that support end device applications with specialized classes for metering and premises area network devices, and remote reading functions. These classes are generally associated with the point where a service is delivered to the customer.</Comment>
      <ParentPackage name="IEC61968"
                     basePackage="http://iec.ch/TC57/CIM100#Package_IEC61968"/>
   </Package>
   <Package name="TC57CIM" basePackage="http://iec.ch/TC57/CIM100#Package_TC57CIM">
      <Comment>The IEC 61968 subpackages of the CIM are developed, standardized and maintained by the UCA community including its working groups and task forces.</Comment>
      <Comment>Currently, normative parts of the model support the needs of information exchange defined in IEC 61968-3, IEC 61968-4, IEC 61968-5, IEC 61968-6, IEC 61968-8, IEC 61968-9 and in IEC 61968-13.</Comment>
   </Package>
   <Root name="DemandResponseProgram"
         baseClass="http://iec.ch/TC57/CIM100#DemandResponseProgram"
         package="Metering"
         packageURI="http://iec.ch/TC57/CIM100#Package_Metering"
         minOccurs="0"
         maxOccurs="unbounded">
      <Comment>Demand response program.</Comment>
      <Stereotype label="Concrete">http://langdale.com.au/2005/UML#concrete</Stereotype>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="mRID"
              baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.mRID"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Master resource identifier issued by a model authority. The mRID is unique within an exchange context. Global uniqueness is easily achieved by using a UUID, as specified in RFC 4122, for the mRID. The use of UUID is strongly recommended.</Comment>
         <Comment>For CIMXML data files in RDF syntax conforming to IEC 61970-552, the mRID is mapped to rdf:ID or rdf:about attributes that identify CIM object elements.</Comment>
      </Simple>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="type"
              baseProperty="http://iec.ch/TC57/CIM100#DemandResponseProgram.type"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Type of demand response program; examples are CPP (critical-peak pricing), RTP (real-time pricing), DLC (direct load control), DBP (demand bidding program), BIP (base interruptible program). Note that possible types change a lot and it would be impossible to enumerate them all.</Comment>
      </Simple>
      <Instance baseClass="http://iec.ch/TC57/CIM100#Name"
                type="Name"
                name="Names"
                baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names"
                minOccurs="0"
                maxOccurs="unbounded"
                inverseBaseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject">
         <Comment>All names of this identified object.</Comment>
      </Instance>
      <InverseInstance baseClass="http://iec.ch/TC57/CIM100#IdentifiedObject"
                       type="IdentifiedObject"
                       name="IdentifiedObject"
                       baseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject"
                       minOccurs="0"
                       maxOccurs="1"
                       inverseBaseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names">
         <Comment>Identified object that this name designates.</Comment>
      </InverseInstance>
   </Root>
   <ComplexType name="Name"
                baseClass="http://iec.ch/TC57/CIM100#Name"
                package="Core"
                packageURI="http://iec.ch/TC57/CIM100#Package_Core"
                minOccurs="0"
                maxOccurs="unbounded">
      <Comment>The Name class provides the means to define any number of human readable  names for an object. A name is &lt;b&gt;not&lt;/b&gt; to be used for defining inter-object relationships. For inter-object relationships instead use the object identification 'mRID'.</Comment>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="name"
              baseProperty="http://iec.ch/TC57/CIM100#Name.name"
              minOccurs="1"
              maxOccurs="1">
         <Comment>Any free text that name the object.</Comment>
      </Simple>
      <Instance baseClass="http://iec.ch/TC57/CIM100#NameType"
                type="NameType"
                name="NameType"
                baseProperty="http://iec.ch/TC57/CIM100#Name.NameType"
                minOccurs="0"
                maxOccurs="1"
                inverseBaseProperty="http://iec.ch/TC57/CIM100#NameType.Names">
         <Comment>Type of this name.</Comment>
      </Instance>
      <InverseInstance baseClass="http://iec.ch/TC57/CIM100#Name"
                       type="Name"
                       name="Names"
                       baseProperty="http://iec.ch/TC57/CIM100#NameType.Names"
                       minOccurs="0"
                       maxOccurs="unbounded"
                       inverseBaseProperty="http://iec.ch/TC57/CIM100#Name.NameType">
         <Comment>All names of this type.</Comment>
      </InverseInstance>
   </ComplexType>
   <ComplexType name="NameType"
                baseClass="http://iec.ch/TC57/CIM100#NameType"
                package="Core"
                packageURI="http://iec.ch/TC57/CIM100#Package_Core"
                minOccurs="0"
                maxOccurs="unbounded">
      <Comment>Type of name. Possible values for attribute 'name' are implementation dependent but standard profiles may specify types. An enterprise may have multiple IT systems each having its own local name for the same object, e.g. a planning system may have different names from an EMS. An object may also have different names within the same IT system, e.g. localName as defined in CIM version 14. The definition from CIM14 is:</Comment>
      <Comment>The localName is a human readable name of the object. It is a free text name local to a node in a naming hierarchy similar to a file directory structure. A power system related naming hierarchy may be: Substation, VoltageLevel, Equipment etc. Children of the same parent in such a hierarchy have names that typically are unique among them.</Comment>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="description"
              baseProperty="http://iec.ch/TC57/CIM100#NameType.description"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Description of the name type.</Comment>
      </Simple>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="name"
              baseProperty="http://iec.ch/TC57/CIM100#NameType.name"
              minOccurs="1"
              maxOccurs="1">
         <Comment>Name of the name type.</Comment>
      </Simple>
      <Instance baseClass="http://iec.ch/TC57/CIM100#NameTypeAuthority"
                type="NameTypeAuthority"
                name="NameTypeAuthority"
                baseProperty="http://iec.ch/TC57/CIM100#NameType.NameTypeAuthority"
                minOccurs="0"
                maxOccurs="1"
                inverseBaseProperty="http://iec.ch/TC57/CIM100#NameTypeAuthority.NameTypes">
         <Comment>Authority responsible for managing names of this type.</Comment>
      </Instance>
      <InverseInstance baseClass="http://iec.ch/TC57/CIM100#NameType"
                       type="NameType"
                       name="NameTypes"
                       baseProperty="http://iec.ch/TC57/CIM100#NameTypeAuthority.NameTypes"
                       minOccurs="0"
                       maxOccurs="unbounded"
                       inverseBaseProperty="http://iec.ch/TC57/CIM100#NameType.NameTypeAuthority">
         <Comment>All name types managed by this authority.</Comment>
      </InverseInstance>
   </ComplexType>
   <ComplexType name="NameTypeAuthority"
                baseClass="http://iec.ch/TC57/CIM100#NameTypeAuthority"
                package="Core"
                packageURI="http://iec.ch/TC57/CIM100#Package_Core"
                minOccurs="0"
                maxOccurs="unbounded">
      <Comment>Authority responsible for creation and management of names of a given type; typically an organization or an enterprise system.</Comment>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="description"
              baseProperty="http://iec.ch/TC57/CIM100#NameTypeAuthority.description"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Description of the name type authority.</Comment>
      </Simple>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="name"
              baseProperty="http://iec.ch/TC57/CIM100#NameTypeAuthority.name"
              minOccurs="1"
              maxOccurs="1">
         <Comment>Name of the name type authority.</Comment>
      </Simple>
   </ComplexType>
   <Root name="UsagePoint"
         baseClass="http://iec.ch/TC57/CIM100#UsagePoint"
         package="Metering"
         packageURI="http://iec.ch/TC57/CIM100#Package_Metering"
         minOccurs="0"
         maxOccurs="unbounded">
      <Comment>Logical or physical point in the network to which readings or events may be attributed. Used at the place where a physical or virtual meter may be located; however, it is not required that a meter be present.</Comment>
      <Stereotype label="Concrete">http://langdale.com.au/2005/UML#concrete</Stereotype>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="mRID"
              baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.mRID"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Master resource identifier issued by a model authority. The mRID is unique within an exchange context. Global uniqueness is easily achieved by using a UUID, as specified in RFC 4122, for the mRID. The use of UUID is strongly recommended.</Comment>
         <Comment>For CIMXML data files in RDF syntax conforming to IEC 61970-552, the mRID is mapped to rdf:ID or rdf:about attributes that identify CIM object elements.</Comment>
      </Simple>
      <Instance baseClass="http://iec.ch/TC57/CIM100#Name"
                type="Name"
                name="Names"
                baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names"
                minOccurs="0"
                maxOccurs="unbounded"
                inverseBaseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject">
         <Comment>All names of this identified object.</Comment>
      </Instance>
      <InverseInstance baseClass="http://iec.ch/TC57/CIM100#IdentifiedObject"
                       type="IdentifiedObject"
                       name="IdentifiedObject"
                       baseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject"
                       minOccurs="0"
                       maxOccurs="1"
                       inverseBaseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names">
         <Comment>Identified object that this name designates.</Comment>
      </InverseInstance>
   </Root>
   <Root name="UsagePointGroup"
         baseClass="http://iec.ch/TC57/CIM100#UsagePointGroup"
         package="Metering"
         packageURI="http://iec.ch/TC57/CIM100#Package_Metering"
         minOccurs="0"
         maxOccurs="unbounded">
      <Comment>Abstraction for management of group communications within a two-way AMR system or the data for a group of related usage points. Commands can be issued to all of the usage points that belong to a usage point group using a defined group address and the underlying AMR communication infrastructure.</Comment>
      <Stereotype label="Concrete">http://langdale.com.au/2005/UML#concrete</Stereotype>
      <Simple dataType="http://www.w3.org/2001/XMLSchema#string"
              xstype="string"
              name="mRID"
              baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.mRID"
              minOccurs="0"
              maxOccurs="1">
         <Comment>Master resource identifier issued by a model authority. The mRID is unique within an exchange context. Global uniqueness is easily achieved by using a UUID, as specified in RFC 4122, for the mRID. The use of UUID is strongly recommended.</Comment>
         <Comment>For CIMXML data files in RDF syntax conforming to IEC 61970-552, the mRID is mapped to rdf:ID or rdf:about attributes that identify CIM object elements.</Comment>
      </Simple>
      <Instance baseClass="http://iec.ch/TC57/CIM100#Name"
                type="Name"
                name="Names"
                baseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names"
                minOccurs="0"
                maxOccurs="unbounded"
                inverseBaseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject">
         <Comment>All names of this identified object.</Comment>
      </Instance>
      <InverseInstance baseClass="http://iec.ch/TC57/CIM100#IdentifiedObject"
                       type="IdentifiedObject"
                       name="IdentifiedObject"
                       baseProperty="http://iec.ch/TC57/CIM100#Name.IdentifiedObject"
                       minOccurs="0"
                       maxOccurs="1"
                       inverseBaseProperty="http://iec.ch/TC57/CIM100#IdentifiedObject.Names">
         <Comment>Identified object that this name designates.</Comment>
      </InverseInstance>
   </Root>
</Catalog>

Creating and Submitting a Custom Builder

The following approach is recommended for creating, testing and submitting a custom builder.

Step 1: Create a Branch to Work In

You can start via one of two options. Either you can fork the CIMTool-Builders-Library repository, perform your work and then create a pull request (see Step 5 below). Alternately, you can request to be added as a collaborator on the CIMTool-Builders-Library project and create a branch off of main to develop your custom builder. A branch will isolate your development work from other branches in the repository.

We ask you to name your branch to match what your XSLT will be named (e.g. google-proto-buffers.xsl).

Step 2: Builder Setup Conventions

Once you have created and cloned your branch make a subfolder under custom-builders that matches the name of your builder minus the .xsl extension.

Make a copy of the\builder-submissions\builder-submission-template.md file and place it in your newly created subfolder. Rename it to builder.md and update its contents as outlined in the instructions contained in it. Feel free to review other builders as examples.

If you are deriving an XSLT from an existing builder then copy the builder into your new folder and rename it. By convention the name of your .xsl should match the folder name plus the .xsl file extension. If creating a new XSLT builder be sure to include the Apache 2.0 copyright header as shown next. This is the copyright associated with the XSLT builder and not that included in the generated output:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2024 UCAIug

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and
  limitations under the License.
-->
<xsl:stylesheet exclude-result-prefixes="a"
    version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:a="http://langdale.com.au/2005/Message#"
    xmlns:sawsdl="http://www.w3.org/ns/sawsdl">

    <xsl:output xmlns:xalan="http://xml.apache.org/xslt" method="xml" omit-xml-declaration="no" indent="yes" xalan:indent-amount="4" />
    <xsl:param name="copyright" />
    <xsl:param name="version"/>
    <xsl:param name="baseURI"/>
    <xsl:param name="ontologyURI"/>
    <xsl:param name="envelope">Profile</xsl:param>
      ...
      ...
      ...
</xsl:stylesheet>

Step 3: Developing Your Builder

Overview of Internal Profile Representation

Below is a comprehensive list of elements that may appear in the .xml internal representation of a profile used as input to XSLT builders. Some builders handle all of them while others ignore in-lined anonymous definitions. Which way you implement your builder is highly dependent on the output that your builder will be generating. For example, the xsd.xsl and json-schema-draft-07.xsl schema builders handle the in-line type definition elements since the specifications for those output types support anonymous in-lined type definitions. However, the scala.xsl, profile-doc-rtf.xsl, and sql.xsl builders do not. The recommendation is to handle them in your builder if your builder's generated output type supports them.

The top-level elements that appear in an .xml profile indicate the various types defined and used in a profile and may include the following:

  • Root elements - all types declared as 'concrete' in the profile
  • ComplexType elements - non-concrete types in the profile (i.e. abstract types)
  • CompoundType elements - types in the profile stereotyped as <<Compound>> in the CIM
  • EnumeratedType elements - types in the profile that are CIM enumerations
  • SimpleType elements - types in the profile stereotyped as <<CIMDatatype>> in the CIM

A top-level type further specifies child elements that indicate the attributes or associations defined for it. These elements may be from the set:

  • Simple elements - represent attributes defined as primitive types in the CIM. These elements will contain an @xstype attribute to specify the primitive.
  • Instance elements - represent associations in the profile. These elements will contain a @type attribute to specify the type within the profile that the association references.
  • InverseInstance elements - an InverseInstance element will always accompany an Instance element in the profile and as the name implies will represent the inverse of the association defined by the Instance element. It is specifically included for XSLT builders that may need to know this (e.g. commonly RDFS builders)
  • Reference elements - also represent associations but ones that must be handled uniquely. These elements will contain a @type attribute to specify the type the reference association is for. The referent may or may not be represented elsewhere in the profile. When the referent is not represented in the profile, and thus is external to the profile, it may be defined in the contextual model as an abstract class with no concrete sub classes. XSLT builders may transform these elements into a variety of different ways depending on the type of builder and the specific target output. In the case of xsd.xsl and json-schema-draft-2020-12.xsl builders additional attributes/elements named ref and referenceType are generated in the target output. The ref is used to hold an identifier (i.e. used for the purposes of referencing) and an optional referenceType used to define the kind of identifier specified by the ref (e.g. 'mRID' or 'Names.name'). This unique mapping relevant for XSD and JSON schema generation is formally defined within the IEC 62361-100 and IEC 62361-104 standards respectively. Other builders may handle output for Reference elements in a completley different manner (see: rdfs-2020.xsl for example)
  • InverseReference elements - an InverseReference element will always accompany a Reference element in the profile and as the name implies will represent the inverse of the association defined by the Reference element. It is specifically included for XSLT builders that may need to know this (e.g. commonly RDFS builders)
  • Domain elements - represent attributes that have a type defined that corresponds to a <<CIMDatatype>> class in the CIM. These types currently resolve to a primitive in CIMTool and therefore the XML child element will contain an @xstype attribute to specify the primitive.
  • Enumerated elements - represents an attribute in a class who's referent type is an enumeration defined in the profile. These elements will contain a @type attribute to specify the referent enumeration.
  • Choice elements - represents a union property defined for a class which is an association that references a super class in the profile. In this context, the union property essentially offers a choice for what the referent type can be. Specifically, the options for the referent type are the subclasses of the union superclass defined in the profile.

There are two additional specialized cases of child elements for specifying an attribute or association defined for a type. These represent what might be described as an in-lined anonymous definition for the referent type of the attribute or association. They do not represent an actual UML construct in the CIM but rather a particular profiling approach relevant to specific target schema specifications or generated output types (e.g. XSD and JSON schema or anonymous types in Java) that support such in-line anonymous types (see: Associations and Anonymous Classes and Why There Are so Many Top Level Definitions in an XML Schema Profile - these articles also are provided as PDF files in the \articles folder). The child elements for these specialized cases are:

  • SimpleEnumerated elements - a variant of Enumerated this element represents an attribute in a class who's referent type is an enumeration. However, this variant will not contain a @type attribute to specify the referent enumeration. Rather the enumeration is defined anonymously as an in-lined type definition. See the xsd.xsl and json-schema-draft-2020-12.xsl for examples of builders handling SimpleEnumerated elements.
  • Complex elements - a variant of ComplexType this element represents an association in a class who's referent type is a CIM class. However, this element will not contain a @type attribute to specify the referent type. Rather the type is defined anonymously as an in-lined type definition. Again, see the xsd.xsl and json-schema-draft-2020-12.xsl for examples of builders handling Complex elements.

Finally, there are a couple of additional elements to highlight that are used for specific purposes within the internal representation:

  • Comment elements - represent a comment that appears on either a class, attribute or association role end.
  • EnumeratedValue elements - this element only appears within the EnumeratedType or SimpleEnumerated elements and represents an enumeration literal defined for the enumeration.
  • SuperType elements - may be present in either a Root or ComplexType element to indicate the parent/super type of the class represented by the Root or ComplexType.

Development and Testing

Turning now to developing and testing your builder. Provided in the table at the end of this README is a list of tooling both free and commercial for developing and testing XSLT transforms. This list is by no means comprehensive but is a good starting point. The intent is that one of these options (or a similar option) is used to create, edit and debug your XSLT builder using the .xml internal representations as input. Each of the individual toolsets outlined has its own instructions on how to run/debug XSLTs in their environments. You can utilize one of the existing stable builders in this library to experiment with in the environment. For an introductory tutorial on XSLT visit the W3C XSLT tutorial.

Also provided in the /builder-submissions folder in this repository is the CIMTool-Test-Project. This project contains two .owl profiles along with their respective .xml files. The EndDeviceControlsTestProfileWithAnonymousTypes.owl profile and its corresponding EndDeviceControlsTestProfileWithAnonymousTypes.xml contain all possible XML elements as just described while the EndDeviceControlsTestProfile.owl and its corresponding EndDeviceControlsTestProfile.xml file are defined without anonymous type definitions. The project has been provided as a matter of convenience. You can use it to create your own profile definitions or utilize just the pre-generated .xml files for testing your builder depending on whether your builder's target output supports anonymous classes.

Internal XSLT Parameters Passed By CIMTool

Finally, CIMTool passes along the following parameters into all XSLT builders:

  • baseURI - the baseURI is the namespace specified in the Namespace field on the Profile Summary tab for a profile.
  • ontologyURI - the ontologyURI is the namespace URI specified at the time a CIM schema is imported into a CIMTool project. It is the URI that appears in the 'Namespace URI' field on properties dialog for the schema. Some builders needed this additional URI for use in their generated output (refer to the rdfs-2020.xsl for an example).
  • envelope - the envelope is the value specified in the Name field on the Description tab for the profile.
  • copyright - the text of a multi-line copyright if one is configured for the project.
  • copyright-single-line - the text of a single-line copyright if one is configured for the project.

For copyright support you must determine which of the two your builder will use. Most likely your builder will utilize the multiline copyright. Refer to existing builders in this library for examples of how each of these internally passed parameters are used. The JSON schema related builders provide an example of utilizing the copyright-single-line as JSON has certain constraints related to carriage returns in descriptions and comments within schemas and therefore requies a single line copyright notice.

NTE (Name/Type/Extension) Assignment

All builders have what is referred to as a NTE (Name/Type/Extension) configuration entry assigned to them when imported into CIMTool. This information is used internally by CIMTool for different purposes.

The Name component of a NTE is static and is auto-assigned during import and is based on the file name of the XSLT file minus the .xsl extension. You should stick to standard ascii alphanumeric characters and avoid any special characters in your XSLT file name.

For the Type component assigned to the builder there are three variants of XSLT transforms that your builder can be categorized in. As to which variant your builder falls into is dependent upon the type of output it will be generating:

  • XSD - This type should only be used if your are generating an XSD based schema as your output. This is because specialized validation on XSDs are performed after they are generated by this category of builder.
  • TEXT - This type is typically assigned for builders that generating some type of code such as Java, C#, Python, etc.
  • TRANSFORM - This is the most generalized category. Examples of existing builders that fall into this category are the profile-doc-rtf.xsl which generates an MS Word document in the RTF (Rich Text Format).

Finally, the Extension component of your assigned NTE is literally the extension that will be used for the file generated by your builder. It must be unique relative to other builders in the CIMTool-Builders-Library repository. Example extensions and the corresponding output files for a ficticious profile named SubstationEquipment:

  • schema.json - SubstationEquipment.schema.json
  • xsd - SubstationEquipment.xsd
  • simplified-doc.rtf - SubstationEquipment.simplified-doc.rtf

Please note that you can experiment with your builder and test it by assigning a type of TEXT during import and review what CIMTool generates. If there are issues delete the builder using the 'Maintain XSLT Builders' dialog (shown earlier) and reimport your builder as a TRANSFORM builder and recheck your output. This has been known to correct issues for certain builders that for example had their encoding set to ASCII:

<xsl:output indent="no" method="text" encoding="ASCII"/>

Step 4: Final Pre-Commit Checklist for Review

Once you've determined your builder is ready confirm the following items:

  1. The detailed description in your builder.md has been completed. If there are particular aspects of your builder that should be highlighted this should be done here. For example, if your builder warrants it, you may include images in your builder's folder and display them within the description section of your builder.md file. A great example of this is the profile-doc-rtf.xsl builder.
  2. You've uploaded a NTE (Name/Type/Extension) Import wizard screenshot named import-builder.png (e.g. import-builder.png) file to your custom builder's folder. You can refer to existing builders as examples.
  3. Your builder is using either the $copyright or $copyright-single-line parameter to generate a copyright as part of its generated output. A copyright is relevant for most builders.
  4. You have added a new row to the Community Developed Builders table in this README. The description in the row entry is typically a simplified version of the description in your builder's builders.md summarizing your builder.

Step 5: Pull Request

When ready, commit your changes, push to GitHub, and create a Pull request so that your commits can be reviewed and approved for inclusion in the library.

Commercial and Open Source XSLT Editors/Debuggers

Third-party tooling can be used to create and test new XSLT transforms for use as builders. The table below provides a examples of available free and commercial products.

Product / Edition Description
image Eclipse Foundation's XSLT Project
(Free)
XSL Tools brings XSLT development to the Eclipse platform. Its scope is to provide basic XSL editing and debugging support to compliment and leverage the XML and source editing support within Web Tools Platform.

The XSL Tools project focuses specifically on the Transformation engine of the W3C XSL Specification. This project is concerned with the XSL Transformation language for XSLT 1.0 and XSLT 2.0.
image XSLT/XPath extensions for Visual Studio Code
(Free)
This VSCode extension provides comprehensive language support for XSLT 3.0 and XPath 3.1. Visit the Quick Start ReadMe or the full XSLT/XPath User Guide for a more comprehensive overview.

For an introduction to the XSLT 3.0 features available in this XSLT/XPath extension for Visual Studio Code view this YouTube video.

Note: Microsoft's free Visual Studio Code is a streamlined code editor with support for development operations like debugging, task running, and version control. It aims to provide just the tools a developer needs for a quick code-build-debug cycle and leaves more complex workflows to fuller featured IDEs, such as Visual Studio IDE
image Altova XMLSpy Enterprise Edition
Altova XMLSpy Professional Edition
(Commercial products)
XMLSpy provides a rich XSLT Editor, Profiler, and Debugger that supports:
  • XSLT 1.0, XSLT 2.0, and XSLT 3.0
  • syntax coloring, line numbering, bookmarking, source folding, & code completion
  • interactive XPath Building and Testing
  • XSLT validation & troubleshooting
For detailed information visit XSLT/XPath User Guide for XMLSpy Enterprise Edition or Processing with XSLT and XQuery using XMLSpy Professional Edition.
image Oxygen XML Developer
(Commercial products)

Oxygen XML Developer offers a powerful XSLT and XQuery debugger that provides full control over the debugging process. Two dedicated perspectives are available, one for XSLT and one for XQuery debugging, both offering specialized views and actions that allow you to troubleshoot and perfect your documents. Visit their Oxygen XML Developer overview page for more details.
image Enterprise Architect
(Commercial product)
Enterprise Architect provides basic facilities for modeling and executing XSL Transforms that can be used to convert XML input documents into other types of documents. Stylesheets are the XSL components used to transform the content. Note that the XSL processor used in EA is built from the Apache Xalan Project so you will be limited to XSLT 1.0 compliant transform builders.

Visit the Sparx EA online user guide for information on how to model, execute and debug XSL transforms from within EA.
[EditX] EditiX XSLT Editor
(Commercial product)
  • XSLT 1.0 / 2.0 / 3.0 editor
  • Debugger with breakpoints (current, next elements, next breakpoint)
  • Debugger with XPath context and XSLT location
  • Syntax colors for XSLT elements and output elements
  • XML Data source preview
  • XML Output preview
Visit the XSLT Editor page for details.

License

Distributed under the Apache 2.0 license. See LICENSE for more information.