[Feature] Minimal IUCLID export (#338)

This is an initial implementation that creates a working minimal .i6z document.
It passes schema validation and can be imported into IUCLID.

Caveat:
IUCLID files target individual compounds.
Pathway is not actually covered by the format.

It can be added in either soil or water and soil OECD endpoints.
**I currently only implemented the soil endpoint for all data.**

This sort of works, and I can report all degradation products in a pathway (not a nice view, but we can report many transformation products and add a diagram attachment in the future).

Adding additional information is an absolute pain, as we need to explicitly map each type of information to the relevant OECD field.
I use the XSD scheme for validation, but unfortunately the IUCLID parser is not fully compliant and requires a specific order, etc.

The workflow is: finding the AI structure from the XSD scheme -> make the scheme validation pass -> upload to IUCLID to get obscure error messages -> guess what could be wrong -> repeat 💣

New specifications get released once per year, so we will have to update accordingly.
I believe that this should be a more expensive feature, as it requires significant effort to uphold.

Currently implemented for root compound only in SOIL:

- Soil Texture 2
- Soil Texture 1
- pH value
- Half-life per soil sample / scenario (mapped to disappearance; not sure about that).
- CEC
- Organic Matter (only Carbon)
- Moisture content
- Humidity

<img width="2123" alt="image.png" src="attachments/d29830e1-65ef-4136-8939-1825e0959c62">
<img width="2124" alt="image.png" src="attachments/ac9de2ac-bf68-4ba4-b40b-82f810a9de93">
<img width="2139" alt="image.png" src="attachments/5674c7e6-865e-420e-974a-6b825b331e6c">

Reviewed-on: enviPath/enviPy#338
Co-authored-by: Tobias O <tobias.olenyi@envipath.com>
Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
This commit is contained in:
2026-04-07 19:46:12 +12:00
committed by jebus
parent f7c45b8015
commit d06bd0d4fd
49 changed files with 66402 additions and 1014 deletions

View File

@ -0,0 +1,237 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://iuclid6.echa.europa.eu/namespaces/REFERENCE_SUBSTANCE/10.0" xmlns:ct="http://iuclid6.echa.europa.eu/namespaces/domain/v10" xmlns:i6="http://iuclid6.echa.europa.eu/namespaces/platform-fields/v1" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://iuclid6.echa.europa.eu/namespaces/REFERENCE_SUBSTANCE/10.0">
<xs:import namespace="http://iuclid6.echa.europa.eu/namespaces/platform-fields/v1" schemaLocation="platform-fields.xsd"/>
<xs:import namespace="http://iuclid6.echa.europa.eu/namespaces/domain/v10" schemaLocation="commonTypesDomainV10.xsd"/>
<xs:element name="REFERENCE_SUBSTANCE">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="DataProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="ReferenceSubstanceName">
<xs:simpleType>
<xs:restriction base="i6:textFieldMultiLine">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="IupacName" type="i6:textFieldMultiLine"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Description" type="i6:multilingualTextFieldLarge"/>
<xs:element minOccurs="0" name="Inventory">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="InventoryEntry">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry" type="i6:inventoryEntry"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="InventoryEntryJustification">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N95"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="remarks" type="i6:multilingualTextField"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="CASNumber" type="i6:textFieldSmall"/>
<xs:element minOccurs="0" name="CASName" type="i6:textFieldMultiLine"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Synonyms">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="Synonyms">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:repeatableEntryType">
<xs:sequence>
<xs:element minOccurs="0" name="DataProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Identifier">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:PG6_60192"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Name" type="i6:textFieldMultiLine"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Remarks" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="MolecularStructuralInfo">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="DataProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="MolecularFormula" type="i6:textFieldMultiLine"/>
<xs:element minOccurs="0" name="MolecularWeightRange">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePhysicalQuantityRangeField">
<xs:sequence>
<xs:element minOccurs="0" name="lowerQualifier" type="i6:lowerQualifier"/>
<xs:element minOccurs="0" name="upperQualifier" type="i6:upperQualifier"/>
<xs:element minOccurs="0" name="lowerValue" type="xs:decimal"/>
<xs:element minOccurs="0" name="upperValue" type="xs:decimal"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="SmilesNotation" type="i6:textFieldMultiLine"/>
<xs:element minOccurs="0" name="InChl" type="i6:textFieldMultiLine"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="InChIKey" type="i6:multilingualTextFieldSmall"/>
<xs:element minOccurs="0" name="StructuralFormula" type="i6:attachmentField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Remarks" type="i6:multilingualTextFieldLarge"/>
<xs:element minOccurs="0" name="ChemicalStructureFiles">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:repeatableEntryType">
<xs:sequence>
<xs:element minOccurs="0" name="StructureFile" type="i6:attachmentField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="RemarksChemStruct" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="RelatedSubstances">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="RelatedSubstances">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:repeatableEntryType">
<xs:sequence>
<xs:element minOccurs="0" name="Identifier">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:PG6_60192"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Identity" type="i6:textFieldLarge"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Remarks" type="i6:multilingualTextFieldSmall"/>
<xs:element minOccurs="0" name="Relation">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N05"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="GroupCategoryInfo" type="i6:multilingualTextFieldMultiLine"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://iuclid6.echa.europa.eu/namespaces/SUBSTANCE/10.0" xmlns:ct="http://iuclid6.echa.europa.eu/namespaces/domain/v10" xmlns:i6="http://iuclid6.echa.europa.eu/namespaces/platform-fields/v1" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://iuclid6.echa.europa.eu/namespaces/SUBSTANCE/10.0">
<xs:import namespace="http://iuclid6.echa.europa.eu/namespaces/platform-fields/v1" schemaLocation="platform-fields.xsd"/>
<xs:import namespace="http://iuclid6.echa.europa.eu/namespaces/domain/v10" schemaLocation="commonTypesDomainV10.xsd"/>
<xs:element name="SUBSTANCE">
<xs:complexType>
<xs:sequence>
<xs:element name="Templates">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Template" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ChemicalName">
<xs:simpleType>
<xs:restriction base="i6:textFieldMultiLine">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="PublicName" type="i6:textFieldMultiLine"/>
<xs:element minOccurs="0" name="OtherNames">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:repeatableEntryType">
<xs:sequence>
<xs:element minOccurs="0" name="DataProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="NameType">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N97"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Name" type="i6:textFieldMultiLine"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Country">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:A31"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Relation">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:PG6_60200"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Remarks" type="i6:multilingualTextFieldLarge"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="OwnerLegalEntityProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="OwnerLegalEntity" type="i6:documentReferenceField"/>
<xs:element minOccurs="0" name="ThirdPartyProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="ThirdParty" type="i6:documentReferenceField"/>
<xs:element minOccurs="0" name="ContactPersons">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:repeatableEntryType">
<xs:sequence>
<xs:element minOccurs="0" name="DataProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="ContactPerson" type="i6:documentReferenceField"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="ReferenceSubstance">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="Protection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="ReferenceSubstance" type="i6:documentReferenceField"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="TypeOfSubstance">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="Composition">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N08"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Origin">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:basePicklistField">
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N58"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other" type="i6:multilingualTextFieldSmall"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="RoleInSupplyChain">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="RoleProtection">
<xs:complexType>
<xs:complexContent>
<xs:extension base="i6:baseDataProtectionField">
<xs:sequence>
<xs:element minOccurs="0" name="confidentiality" type="ct:N64"/>
<xs:element minOccurs="0" name="justification" type="i6:textField"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="legislation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="ct:N78"/>
<xs:element minOccurs="0" name="other" type="i6:textFieldSmall"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Manufacturer" nillable="true" type="i6:booleanField"/>
<xs:element minOccurs="0" name="Importer" nillable="true" type="i6:booleanField"/>
<xs:element minOccurs="0" name="OnlyRepresentative" nillable="true" type="i6:booleanField"/>
<xs:element minOccurs="0" name="DownstreamUser" nillable="true" type="i6:booleanField"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

File diff suppressed because it is too large Load Diff