Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Authoring XML Schemas for use with EMF"

Line 1: Line 1:
 +
{| align="right"
 +
| __TOC__
 +
|}
 +
 
This article focuses on authoring and using XML Schemas for the purpose of generating an EMF model.
 
This article focuses on authoring and using XML Schemas for the purpose of generating an EMF model.
  
 
= Introduction =
 
= Introduction =
  
An '''EMF Model''' (files of type *.genmodel) is the hub for importing/exporting other metamodel formats, linking to other EMF models, and generating implementation code. Out-of-the-box, EMF can import '''XML Schema Definitions (XSDs)''' into '''Ecore Models''' (files of type *.ecore). Similarly, EMF can export Ecore Models to XSDs. But without some additional information, EMF uses a default set of transformations that rarely yields the desired results.
+
An '''EMF Model''' (files of type *.genmodel) is your hub for importing/exporting other metamodel formats, linking to other EMF models, and generating implementation code. Out-of-the-box, EMF can import '''XML Schema Definitions (XSDs)''' into '''Ecore Models''' (files of type *.ecore). Similarly, EMF can export Ecore Models to XSDs. But without some additional information, EMF uses a default set of transformations that rarely yields the desired results.
  
 
Luckily, both Ecore models and XML Schemas have support for annotations.  Annotations can be almost anything, but for this discussion, annotations will serve two main purposes:
 
Luckily, both Ecore models and XML Schemas have support for annotations.  Annotations can be almost anything, but for this discussion, annotations will serve two main purposes:
Line 13: Line 17:
  
 
This article will focus only on authoring and annotating XSDs, and importing them into Ecore models. However, it is often a useful learning tool to model certain structures first in Ecore, and then export to see the XSD equivalent, including the ecore annotations.
 
This article will focus only on authoring and annotating XSDs, and importing them into Ecore models. However, it is often a useful learning tool to model certain structures first in Ecore, and then export to see the XSD equivalent, including the ecore annotations.
 +
 +
==Reasons to use XSDs with EMF==
 +
 +
==Important Differences between XSDs and Ecore Models==
 +
 +
===Multiple Inheritance===
 +
 +
<table class="gallery" style="margin:1em">
 +
<tr>
 +
<td>EMF's EClass supports multiple inheritance, which allows you to mix-in structural features like attributes at multiple places in your generated class hiearchy. However, the java language does not support multiple ''class'' inheritance, so the actual implementation behind the shared java interface is generated multiple times.
 +
 +
One benefit to using multiple inheritance with EMF is that the metamodel is shared. Clients that use the reflective API or receive model events will see the same shared feature even though the implementation has been duplicated.</td>
 +
<td>XML Schemas do '''not''' support multiple inheritance. A Complex Type can only extend one other Complex Type.
 +
 +
As an approximation, XSDs allow attribute groups do be define. They can be reused multiple times. However, each time an attribute group is reused, it is treated as a copy of those attributes, rather than a shared reference.</td>
 +
</tr>
 +
</table>
 +
 +
===Global Elements and Attributes===
 +
 +
<table class="gallery" style="margin:1em">
 +
<tr>
 +
<td>Ecore's Attributes and References always occur in the context of a containing EClass. They can not be declared on their own, and later pulled in to one or more EClasses.</td>
 +
<td>XSDs allow global elements and attributes to be defined and then referenced multiple times. For the purpose of this discussion, this type of referencing is really a copy.</td>
 +
</tr>
 +
</table>
  
 
==The Transformation Process==
 
==The Transformation Process==
Line 18: Line 48:
 
# An EMF Model is created and associated with one or more XSDs
 
# An EMF Model is created and associated with one or more XSDs
 
# When the Wizard finishes, the conversion process creates *.ecore files
 
# When the Wizard finishes, the conversion process creates *.ecore files
# At this point, EMF will not read your XSDs again. All information needed by EMF has been tucked away somewhere.
+
# At this point, EMF will not read your XSDs again. All information needed by EMF has been tucked away somewhere else.
# Modify your schemas and repeat the process starting from step 2.
+
# If you modify your schemas, the transformation can be performed again from the .genmodel Editor. Affected Ecore models are completely replaced.
  
 
===Which Parts of an XML Schema are Processed?===
 
===Which Parts of an XML Schema are Processed?===
Line 27: Line 57:
 
===What is the Output of the Process===
 
===What is the Output of the Process===
  
The Process generates (or updates) the following:
+
The Process generates, updates, or replaces the following:
  
 
#; Ecore Models
 
#; Ecore Models
Line 46: Line 76:
 
The first thing any ECore model needs is an EPackage. Each XSD imported contains a <schema> element that is mapped to an EPackage. Since the schema element is often the first element, it also defines the namespace prefixes for the entire document.
 
The first thing any ECore model needs is an EPackage. Each XSD imported contains a <schema> element that is mapped to an EPackage. Since the schema element is often the first element, it also defines the namespace prefixes for the entire document.
  
Here is an example schema declaration, showing required and optional attributes:
+
Here is an example schema declaration, showing both required and optional attributes:
  
 
{| cellpadding="0" cellspacing="2px" style="padding:1em; margin-left: 2em; font-family: Courier New; font-height:8pt; background-color:#EEEEEE;"
 
{| cellpadding="0" cellspacing="2px" style="padding:1em; margin-left: 2em; font-family: Courier New; font-height:8pt; background-color:#EEEEEE;"
Line 77: Line 107:
 
; <nowiki>ecore:package="org.example.core.model.countryclub"</nowiki> : The package statement determines both the name of the EPackage, and the full name for the java package of the generated implementation.
 
; <nowiki>ecore:package="org.example.core.model.countryclub"</nowiki> : The package statement determines both the name of the EPackage, and the full name for the java package of the generated implementation.
  
==Customizing Global Elements and Document Content==
+
==Customizing Global Elements or Document Content==
  
 
Schemas contain globally declared elements for the following purposes:
 
Schemas contain globally declared elements for the following purposes:
  
# To define the root elements which can appear in a document
+
# To define root elements which can appear in a document
 
# To declare a replaceable element, which can be substituted by other global elements
 
# To declare a replaceable element, which can be substituted by other global elements
 
# For convenience, to define an Element once, and reference it multiple times from other elements
 
# For convenience, to define an Element once, and reference it multiple times from other elements
  
If the element exists for one of the first two reasons, EMF needs to map the element, which results in a reference on the magical DocumentRoot class in the same Package. Otherwise, you can instruct EMF to ignore the element, and avoiding the generated EReference.
+
If the element exists for one of the first two reasons, EMF needs to map the element, which results in a reference on the magical DocumentRoot class in the same Package. Otherwise, you can instruct EMF to ignore the element.
  
 
{| cellpadding="0" cellspacing="2px" style="padding:1em; margin-left: 2em; font-family: Courier New; font-height:8pt; background-color:#EEEEEE;"
 
{| cellpadding="0" cellspacing="2px" style="padding:1em; margin-left: 2em; font-family: Courier New; font-height:8pt; background-color:#EEEEEE;"

Revision as of 13:53, 14 June 2007

This article focuses on authoring and using XML Schemas for the purpose of generating an EMF model.

Introduction

An EMF Model (files of type *.genmodel) is your hub for importing/exporting other metamodel formats, linking to other EMF models, and generating implementation code. Out-of-the-box, EMF can import XML Schema Definitions (XSDs) into Ecore Models (files of type *.ecore). Similarly, EMF can export Ecore Models to XSDs. But without some additional information, EMF uses a default set of transformations that rarely yields the desired results.

Luckily, both Ecore models and XML Schemas have support for annotations. Annotations can be almost anything, but for this discussion, annotations will serve two main purposes:

  • Provide additional information when transforming one metamodel to another
  • Provide additional information on how to serialize/deserialize your model objects

EMF supports transformations in both directions (to and from XSDs). Currently, if you start with an Ecore model, round-tripping to XSD and back to Ecore should be lossless. However, Ecore supports some structures that have no XSD equivalent, such as multiple inheritance. Information will be lost in such cases. Also, if you start with an XSD, not all of the information will be captured in the Ecore model. Therefore, XSD->Ecore->XSD is not a recommended practice as of the Europa release.

This article will focus only on authoring and annotating XSDs, and importing them into Ecore models. However, it is often a useful learning tool to model certain structures first in Ecore, and then export to see the XSD equivalent, including the ecore annotations.

Reasons to use XSDs with EMF

Important Differences between XSDs and Ecore Models

Multiple Inheritance

Global Elements and Attributes

The Transformation Process

  1. An EMF Model is created and associated with one or more XSDs
  2. When the Wizard finishes, the conversion process creates *.ecore files
  3. At this point, EMF will not read your XSDs again. All information needed by EMF has been tucked away somewhere else.
  4. If you modify your schemas, the transformation can be performed again from the .genmodel Editor. Affected Ecore models are completely replaced.

Which Parts of an XML Schema are Processed?

Without being told otherwise, EMF will process your Schema, all of its globally declared Elements, and all Types contained therein. Other content (e.g. globally-declared Attributes, AttributeGroups, and Groups) is ignored by EMF. These entries are just macros that Elements and Types can reference, effectively in-lining a copy. If two Types reference the same global Attribute, AttributeGroup, or Element, EMF sees them as two distinct features which happen to have identical information.

What is the Output of the Process

The Process generates, updates, or replaces the following:

  1. Ecore Models
    Schemas become Packages; Simple/Complex Types become EClasses, EDataTypes, and EEnums; Elements and Attributes become EStructuralFeatures
    Annotations in your Ecore Models
    Ecore annotations are added in several places to capture the way your model should be serialized/deserialized. These annotations are what enable EMF to read and write XML documents that don't conform to EMF's default serialization format.
    A Helper EClass named "DocumentRoot"
    In certain cases, EMF must create a DocumentRoot class to store additional information.
    Helper EStructuralFeatures, such as feature maps with the suffix "group"
    To handle XSD features like substitution groups, the substitution rule to be used when writing must be known. To handle these cases, your Class' EReferences don't hold onto the actual content, but are instead derived from these "group" references which contains keys in addition to the actual referenced object.
    Your EMF Model
    References to the schemas you imported are kept so that you can invoke a reload later. Generations options are configured the first time with different defaults, under the assumption that you'll be reading and writing to XML files.

Reference Section

Customizing Package Creation

The first thing any ECore model needs is an EPackage. Each XSD imported contains a <schema> element that is mapped to an EPackage. Since the schema element is often the first element, it also defines the namespace prefixes for the entire document.

Here is an example schema declaration, showing both required and optional attributes:

<xs:schema
1) xmlns:cc="http://www.example.org/GolfCountryClub"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
ecore:nsPrefix="cc"
ecore:package="org.example.core.model.countryclub"
targetNamespace="http://www.example.org/GolfCountryClub">
...
</xs:schema>
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" 
Defining the namespace prefix for ecore is necessary when using any ecore markup.
ecore:nsPrefix="cc" 
Setting the nsPrefix determines the prefix used when saving documents.
ecore:package="org.example.core.model.countryclub" 
The package statement determines both the name of the EPackage, and the full name for the java package of the generated implementation.

Customizing Global Elements or Document Content

Schemas contain globally declared elements for the following purposes:

  1. To define root elements which can appear in a document
  2. To declare a replaceable element, which can be substituted by other global elements
  3. For convenience, to define an Element once, and reference it multiple times from other elements

If the element exists for one of the first two reasons, EMF needs to map the element, which results in a reference on the magical DocumentRoot class in the same Package. Otherwise, you can instruct EMF to ignore the element.

...
<xs:element name="GolfCourse"
type="tns:GolfCourse"
ecore:ignore="true"
ecore:name="overrideName"
...
</xs:element>
...
ecore:ignore="true" 
Indicates that the element and any anonymous types in it should be ignored.
ecore:name="overrideName" 
Overrides the name assigned to the feature that is created on the DocumentRoot class. The default is to use the element's name.

Customizing Type Creation

DataTypes

<xs:simpleType name="RGB">
	<xs:restriction base="xs:string"/>
</xs:simpleType>

Enums

<xs:simpleType name="Align">
	<xs:restriction base="xs:string">
		<xs:enumeration value="Left"/>
		<xs:enumeration value="Center"/>
		<xs:enumeration value="Right"/>
	</xs:restriction>
</xs:simpleType>

Customizing the creation of Structural Features

Using Substitution Groups

--Hudsonr.us.ibm.com 14:26, 12 June 2007 (EDT)

Back to the top