Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added a generalized concept for version migration of IDS files via XSLT #244

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 83 additions & 0 deletions Version migration/IDS_Audit_migration.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0"?>

<!--
*
* Author: Marcel Stepien
* Organisation: VSK Software GmbH
* Date: 2024.02.07
* e-Mail: info@vsk-software.com
*
* Applies transformation of IDS developer agreements changes from IDS 0.9.6 to 1.0.
*
-->

<xsl:stylesheet
xmlns:ids="http://standards.buildingsmart.org/IDS"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:param
name="lang_lower"
select="'abcdefghijklmnopqrstuvwxyz'" />

<xsl:param
name="lang_upper"
select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

<!-- IDS-Audit: IFC2x3 schema hint in lower-case for the x only -->
<xsl:template match="ids:specification/@ifcVersion">
<xsl:attribute name="ifcVersion">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)"/>
</xsl:attribute>
</xsl:template>

<!-- IDS-Audit: IFC entity names are printed in upper-case -->
<xsl:template match="ids:entity/ids:name/ids:simpleValue/text()">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)"/>
</xsl:template>

<xsl:template match="ids:entity/ids:name/xs:restriction/xs:enumeration/@value">
<xsl:attribute name="value">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)"/>
</xsl:attribute>
</xsl:template>

<!-- IDS-Audit: upper-case of datatype for version 0.9.6 -->
<xsl:template match="ids:property/@datatype">
<xsl:attribute name="datatype">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)"/>
</xsl:attribute>
</xsl:template>

<!-- IDS-Audit: upper-case of dataType for version 0.9.7 -->
<xsl:template match="ids:property/@dataType">
<xsl:attribute name="dataType">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)"/>
</xsl:attribute>
</xsl:template>

<!-- IDS-Audit: ensure that a base is provided for restrictions, but only if none is provided -->
<xsl:template match="xs:restriction[(./xs:minInclusive or ./xs:maxInclusive or ./xs:minExclusive or ./xs:maxExclusive) and not(@base)]">
<xsl:copy>
<xsl:attribute name="base">xs:double</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="xs:restriction[(./xs:enumeration or ./xs:pattern) and not(@base)]">
<xsl:copy>
<xsl:attribute name="base">xs:string</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
54 changes: 54 additions & 0 deletions Version migration/IDS_v0.9.3-v0.9.6_migration.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0"?>

<!--
*
* Author: Marcel Stepien, Andre Vonthron
* Organisation: VSK Software GmbH
* Date: 2024.01.23
* e-Mail: info@vsk-software.com
*
* Applies transformation changes from IDS 0.9.3 to 0.9.6.
*
-->

<xsl:stylesheet
xmlns:ids="http://standards.buildingsmart.org/IDS"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:param
name="lang_lower"
select="'abcdefghijklmnopqrstuvwxyz'" />

<xsl:param
name="lang_upper"
select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

<!-- IDS-0.9.6: all partOf relations to uppercase -->
<xsl:template match="@relation">
<xsl:attribute name="relation">
<xsl:value-of select="translate(., $lang_lower, $lang_upper)" />
</xsl:attribute>
</xsl:template>

<!-- IDS-0.9.6: renaming measure to datatype -->
<xsl:template match="@measure">
<xsl:attribute name="datatype">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>

<!-- IDS-0.9.6: remove the min- and maxOccurs from the attribute facet -->
<xsl:template match="ids:attribute/@minOccurs" />
<xsl:template match="ids:attribute/@maxOccurs" />

</xsl:stylesheet>
109 changes: 109 additions & 0 deletions Version migration/IDS_v0.9.6-v0.9.7_migration.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?xml version="1.0"?>

<!--
*
* Author: Marcel Stepien, Andre Vonthron
* Organisation: VSK Software GmbH
* Date: 2024.03.03
* e-Mail: info@vsk-software.com
*
* Applies transformation changes from IDS 0.9.6 to 0.9.7.
*
-->

<xsl:stylesheet
xmlns:ids="http://standards.buildingsmart.org/IDS"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<!-- IDS-0.9.7: renaming property -> name to baseName -->
<xsl:template match="ids:property/ids:name">
<ids:baseName>
<xsl:apply-templates select="@*|node()" />
</ids:baseName>
</xsl:template>

<!-- IDS-0.9.7: renaming datatype to dataType -->
<xsl:template match="@datatype">
<xsl:attribute name="dataType">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>

<!--
IDS-0.9.7: remove the min- and maxOccurs from the attribute facet and
replace it with an enum of cardinalities of the interpreted occurs.
-->
<xsl:template match="ids:requirements/*[@minOccurs = '1']">
<xsl:copy>
<xsl:attribute name="cardinality">required</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ids:requirements/*[@minOccurs = '0' and @maxOccurs != '0']">
<xsl:copy>
<xsl:attribute name="cardinality">optional</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ids:requirements/*[@minOccurs = '0' and @maxOccurs = '0']">
<xsl:copy>
<xsl:attribute name="cardinality">prohibited</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="ids:requirements/*[@minOccurs != '0' and @minOccurs != '1']">
<xsl:copy>
<xsl:attribute name="cardinality">required</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<!-- removes the minOccurs and maxOccurs -->
<xsl:template match="ids:requirements/*/@minOccurs" />
<xsl:template match="ids:requirements/*/@maxOccurs" />


<!--
IDS-0.9.7: Adjustments to the partOf-facet. Including the removal of cardinality option of 'optional' (in replacement or required) and
the merged combination of IFCRELAGGREGATES and IFCRELFILLSELEMENT to one combined option.
-->
<xsl:template match="ids:requirements/ids:partOf[@cardinality = 'optional']">
<xsl:copy>
<xsl:attribute name="cardinality">required</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>

<!--
Important note!
Some xsl tranformer may require to exclude the modified attribute manually.
In that case replace the line above with the line below.
-->
<!-- <xsl:apply-templates select="node()|@* except @cardinality"/> -->
</xsl:copy>
</xsl:template>

<xsl:template match="ids:requirements/ids:partOf[@relation = 'IFCRELVOIDSELEMENT' or @relation = 'IFCRELFILLSELEMENT']">
<xsl:copy>
<xsl:attribute name="relation">IFCRELVOIDSELEMENT IFCRELFILLSELEMENT</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>

<!--
Important note!
Some xsl tranformer may require to exclude the modified attribute manually.
In that case replace the line above with the line below.
-->
<!-- <xsl:apply-templates select="node()|@* except @relation"/> -->
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
22 changes: 22 additions & 0 deletions Version migration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Version migration

This page primarily adresses the need for developers to migrate IDS versions.

A workflow using *Extensible Stylesheet Language Transformer* (XSLT) scripts is suggested as a possible strategy for migrating older IDS files to newer versions. Each script formulates its own transformation for the IDS, updating the naming conventions and general structure of an IDS. Most common XSD/XML parsers are able to use XSLT by default. How and when this transformation should be applied depends on the specific use case. However, we recommend considering the integration of script parsing during loading/uploading to enable older versions to be taken into account in newer applications.

The general naming convention of the migration files is as following:

- **IDS_{old version}-{new version}_migration.xsl**

Certain files may diverge in the naming convention, such as specialized transformations regardless of versions and order of migration. The scripts content are written based on XSLT 2.0 and XPath 2.0 language extensions. The following order of transformation is recommended for migration into newer versions:

1. IDS_v0.9.3-v0.9.6_migration
2. IDS_v0.9.6-v0.9.7_migration
3. IDS_Audit_migration

For execution of those XSLT-scripts, numerouse transformer are available online and hosted for free. On the coding side, developers may look into libraries such as:

- Saxon 9 (Java, .NET, Native, JavaScript) ![feature list](https://www.saxonica.com/html/products/feature-matrix-9-9.html)
- AltovaXML 2008
- Xalan-J (Java integration)
- Xalan-C++ (C++ integration)