Home » Modeling » EMF » Loading XML with a schema that extends via substitutionGroup
Loading XML with a schema that extends via substitutionGroup [message #558909] |
Tue, 14 September 2010 20:19 |
Tamar Cohen Messages: 103 Registered: July 2009 |
Senior Member |
|
|
Hello EMF world --
For some reason I have not run into this issue before and despite my internet sleuthing I remain baffled. Here is the problem I am trying to solve:
Description:
I have a schema which I am using for the basis of my EMF genmodel & ecore and generated code. ( http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd) That's all fine and dandy and I've been using that code for more than a year.
There's another schema that extends the above one. I have created a new genmodel and ecore based on the new schema, and had it reference my other ecore files. (http://code.google.com/apis/kml/schema/kml22gx.xsd). This schema extends the first schema, and uses substitutionGroup as follows (focusing on extending altitudeMode):
original kml schema:
<simpleType name="altitudeModeEnumType">
<restriction base="string">
<enumeration value="clampToGround"/>
<enumeration value="relativeToGround"/>
<enumeration value="absolute"/>
</restriction>
</simpleType>
<element name="altitudeModeGroup" abstract="true"/>
<element name="altitudeMode" type="kml:altitudeModeEnumType"
default="clampToGround" substitutionGroup="kml:altitudeModeGroup"/>
<element name="LookAt" type="kml:LookAtType"
substitutionGroup="kml:AbstractViewGroup"/>
<complexType name="LookAtType" final="#all">
<complexContent>
<extension base="kml:AbstractViewType">
<sequence>
<element ref="kml:longitude" minOccurs="0"/>
<element ref="kml:latitude" minOccurs="0"/>
<element ref="kml:altitude" minOccurs="0"/>
<element ref="kml:heading" minOccurs="0"/>
<element ref="kml:tilt" minOccurs="0"/>
<element ref="kml:range" minOccurs="0"/>
<element ref="kml:altitudeModeGroup" minOccurs="0"/>
<element ref="kml:LookAtSimpleExtensionGroup" minOccurs="0"
maxOccurs="unbounded"/>
<element ref="kml:LookAtObjectExtensionGroup" minOccurs="0"
maxOccurs="unbounded"/>
</sequence>
</extension>
</complexContent>
</complexType>
<element name="LookAtSimpleExtensionGroup" abstract="true"
type="anySimpleType"/>
<element name="LookAtObjectExtensionGroup" abstract="true"
substitutionGroup="kml:AbstractObjectGroup"/>
other ext schema:
<simpleType name="altitudeModeEnumType">
<restriction base="string">
<enumeration value="clampToSeaFloor"/>
<enumeration value="relativeToSeaFloor"/>
</restriction>
</simpleType>
<element name="altitudeMode" type="gx:altitudeModeEnumType" substitutionGroup="kml:altitudeModeGroup"/>
Problem:
When I try to load kml files that include stuff from the new schema, the loader fails. In fact it's using the wrong loader; it's not trying to use the ExtFactory but is only using the original KmlFactory.
Sample xml being loaded:
(defines gx namespace: xmlns:gx="http://www.google.com/kml/ext/2.2")
<LookAt>
<longitude>-89.87405323367584</longitude>
<latitude>75.43581734916602</latitude>
<altitude>0</altitude>
<range>224.6819781728186</range>
<tilt>0</tilt>
<heading>-0.01149447949429986</heading>
<altitudeMode>relativeToGround</altitudeMode>
<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
</LookAt>
Exception:
Caused by: java.lang.IllegalArgumentException: The value 'relativeToSeaFloor' is not a valid enumerator of 'AltitudeModeEnumType'
at net.opengis.kml.KmlFactory.createAltitudeModeEnumTypeFromStr ing(KmlFactory.java:910)
at net.opengis.kml.KmlFactory.createFromString(KmlFactory.java: 162)
at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.createFromStrin g(XMLHelperImpl.java:1621)
Code setup:
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap().put(KML, new ExtResourceFactoryImpl());
// Register the package to ensure it is available during loading.
// only needed when running not from plugins.
resourceSet.getPackageRegistry().put(ExtPackage.eNS_URI, ExtPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://earth.google.com/kml/ext/2.2", ExtPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://www.google.com/kml/ext/2.2", ExtPackage.eINSTANCE);
resourceSet.getPackageRegistry().put(KmlPackage.eNS_URI, KmlPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://earth.google.com/kml/2.0", KmlPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://earth.google.com/kml/2.1", KmlPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://earth.google.com/kml/2.2", KmlPackage.eINSTANCE);
resourceSet.getPackageRegistry().put(AtomPackage.eNS_URI, AtomPackage.eINSTANCE);
Question: How do I get the XMLHelperImpl to use the correct ExtFactory to load the extension classes properly?
Thanks for any input!
Tamar
|
|
| | | | | | |
Re: Loading XML with a schema that extends via substitutionGroup [message #662266 is a reply to message #662260] |
Tue, 29 March 2011 23:06 |
Ed Merks Messages: 33218 Registered: July 2009 |
Senior Member |
|
|
Tamar,
Comments below.
Tamar Cohen wrote:
> Hi Ed --
>
> Thanks for your response. Yes, of course enums can't be extended, and
> what I'm trying to figure out is how to get EMF to not generate the
> enum in the first place.
Sorry, I should have mentioned the ecore:enum="false" annotation. You
might only need/want to do it for the second done.
>
> I have modified the xsds as follows:
> <simpleType name="altitudeModeEnumType"
> ecore:instanceClass="java.lang.String" >
> <restriction base="string">
> <enumeration value="clampToGround"/>
> <enumeration value="relativeToGround"/>
> <enumeration value="absolute"/>
> </restriction>
> </simpleType>
>
> <simpleType name="altitudeModeEnumType"
> ecore:instanceClass="java.lang.String" >
> <restriction base="string">
> <enumeration value="clampToSeaFloor"/>
> <enumeration value="relativeToSeaFloor"/>
> </restriction>
> </simpleType>
>
> and I have modified the ecore as follows, adding the baseType:
> <eClassifiers xsi:type="ecore:EDataType" name="AltitudeModeEnumType"
> instanceClassName="java.lang.String">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="altitudeModeEnumType"/>
> <details key="enumeration" value="clampToGround relativeToGround
> absolute"/>
> <details key="baseType"
> value="http://www.eclipse.org/emf/2003/XMLType#string"/>
> </eAnnotations>
> </eClassifiers>
>
> <eClassifiers xsi:type="ecore:EDataType" name="AltitudeModeEnumType"
> instanceClassName="java.lang.String">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="altitudeModeEnumType"/>
> <details key="enumeration" value="clampToSeaFloor
> relativeToSeaFloor"/>
> <details key="baseType"
> value="http://www.eclipse.org/emf/2003/XMLType#string"/>
> </eAnnotations>
> </eClassifiers>
>
> The generated code now is expecting an EObject
I'm not sure I understand
> and the validator wraps the enumeration values, explicitly. I've
> temporarily told the validator to return true (always valid). When
> setting one of these, code like this is generated:
> case KmlPackage.GROUND_OVERLAY_TYPE__ALTITUDE_MODE_GROUP:
> ((FeatureMap.Internal)getAltitudeModeGroup()).set(newValue);
> return;
>
> I am STILL having the same problem, however, in the SAX parser -- XML
> handler.setFeatureValue -- the value defined in the second schema is
> not legal. The newValue coming in is of type SimpleAnyTypeImpl.
I suspect I need a complete (hopefully minimal) example illustrating the
issue so I can look into whether it's a bug or how to get it working.
>
> So ... at least now I'm not generating enums, but it seems that the
> wrong resource factory is being used to load. Is there a way to not
> error out of loading when the SAX parser chokes on something? ie skip
> bad elements?
It kind of does that mostly already. You just might not notice the
resource is in the resource set with contents when you get an exception
while loading it...
>
> thanks
>
> Tamar
>
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| |
Re: Loading XML with a schema that extends via substitutionGroup [message #662472 is a reply to message #662458] |
Wed, 30 March 2011 18:08 |
Tamar Cohen Messages: 103 Registered: July 2009 |
Senior Member |
|
|
Ok -- starting over here, I have a feeling that the generated code is correct and I am doing something wrong in that it's using the wrong loader.
So I may have written some / all of this before but I will post it here just to be clear. I am focusing on AltitudeModeEnumType which is extended in the other schema.
KML Schema from google:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:kml="http://www.opengis.net/kml"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
targetNamespace="http://www.opengis.net/kml"
ecore:ignoreSubstitutionGroups="true"
elementFormDefault="qualified"
version="2.2.0">
<simpleType name="altitudeModeEnumType" ecore:enum="false">
<restriction base="string">
<enumeration value="clampToGround"/>
<enumeration value="relativeToGround"/>
<enumeration value="absolute"/>
</restriction>
</simpleType>
<element name="altitudeModeGroup" abstract="true"/>
<element name="altitudeMode" type="kml:altitudeModeEnumType"
default="clampToGround" substitutionGroup="kml:altitudeModeGroup"/>
GX schema from google (google KML extensions)
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:gx="http://www.google.com/kml/ext"
xmlns:kml="http://www.opengis.net/kml" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
targetNamespace="http://www.google.com/kml/ext" elementFormDefault="qualified" version="090102 BETA"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
ecore:ignoreSubstitutionGroups="true">
<simpleType name="altitudeModeEnumType" ecore:enum="false" >
<restriction base="string">
<enumeration value="clampToSeaFloor"/>
<enumeration value="relativeToSeaFloor"/>
</restriction>
</simpleType>
<element name="altitudeMode" type="gx:altitudeModeEnumType" substitutionGroup="kml:altitudeModeGroup"/>
Usage in a file, note the gx:altitudeMode:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
<Document>
<name>Kelly5m_Rugosity_1_1_1.kml</name>
<GroundOverlay>
<gx:altitudeMode>clampToSeaFloor</gx:altitudeMode>
<drawOrder>20</drawOrder>
<name>Kelly5m_Rugosity_1_1_1.tif</name>
<Icon>
<href>Kelly5m_Rugosity_1_1_1.tif</href>
</Icon>
<LatLonBox>
<north>51.04529905</north>
<south>50.99906962</south>
<east>-121.7097378</east>
<west>-121.7845071</west>
</LatLonBox>
</GroundOverlay>
</Document>
</kml>
So I had created my kml genmodel / ecore files before I was aware of the gx extensions. Subsequently I created ext.genmodel and ext.ecore files which link to the kml.ecore and other ecore files, and generated new code.
I set up the ResourceSet roughly as follows:
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap().put(KML, new ExtResourceFactoryImpl());
resourceSet.getPackageRegistry().put("http://www.google.com/kml/ext/2.2", ExtPackage.eINSTANCE);
resourceSet.getPackageRegistry().put("http://earth.google.com/kml/2.2", KmlPackage.eINSTANCE);
So the Ext (google extension) support should extend the kml loading.
Now with the new ecore:enum="false" in the schema, there is no longer an enum or class generated at all for the AltitudeModeEnumType.
Now, the DocumentRoot in the kml package has:
public String getAltitudeMode() {
return (String)getMixed().get(KmlPackage.Literals.DOCUMENT_ROOT__AL TITUDE_MODE, true);
}
and
public EObject getAltitudeModeGroup() {
return (EObject)getMixed().get(KmlPackage.Literals.DOCUMENT_ROOT__A LTITUDE_MODE_GROUP, true);
}
as does the DocumentRoot in the ext package:
public String getAltitudeMode() {
return (String)getMixed().get(ExtPackage.Literals.DOCUMENT_ROOT__AL TITUDE_MODE, true);
}
(and hmm ... I'm thinking that having 4 different DocumentRoot classes defined is probably a problem).
So the GroundOverlayType defined in kml now has this:
public EObject getAltitudeModeGroup() {
return altitudeModeGroup;
}
Hm. So that was a lot of detailed information yet still not a nice simple example. I guess the question is, what SHOULD I be doing to set up the resource so that a GroundOverlayType defined within the kml package will know to use the ext package to read something that has gx: in it (see above kml). It should now be possible to substitute them since they are not enums.
Thank you
Tamar
|
|
|
Re: Loading XML with a schema that extends via substitutionGroup [message #662516 is a reply to message #662472] |
Wed, 30 March 2011 21:47 |
Ed Merks Messages: 33218 Registered: July 2009 |
Senior Member |
|
|
Tamar,
Comments below.
Tamar Cohen wrote:
> Ok -- starting over here, I have a feeling that the generated code is
> correct and I am doing something wrong in that it's using the wrong
> loader.
>
> So I may have written some / all of this before but I will post it
> here just to be clear. I am focusing on AltitudeModeEnumType which is
> extended in the other schema.
>
> KML Schema from google:
>
> <schema xmlns="http://www.w3.org/2001/XMLSchema"
> xmlns:kml="http://www.opengis.net/kml"
> xmlns:atom="http://www.w3.org/2005/Atom"
> xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
> targetNamespace="http://www.opengis.net/kml"
> ecore:ignoreSubstitutionGroups="true"
> elementFormDefault="qualified"
> version="2.2.0">
>
> <simpleType name="altitudeModeEnumType" ecore:enum="false">
> <restriction base="string">
> <enumeration value="clampToGround"/>
> <enumeration value="relativeToGround"/>
> <enumeration value="absolute"/>
> </restriction>
> </simpleType>
>
> <element name="altitudeModeGroup" abstract="true"/>
Oh, this is completely untyped. So that's like it having type
xsd:anyType. That means even a complex type instance is allowed, so
this maps to a reference of type EObject. I'm doubting you want it to
be that general.
> <element name="altitudeMode" type="kml:altitudeModeEnumType"
> default="clampToGround" substitutionGroup="kml:altitudeModeGroup"/>
>
>
> GX schema from google (google KML extensions)
> <schema xmlns="http://www.w3.org/2001/XMLSchema"
> xmlns:gx="http://www.google.com/kml/ext"
> xmlns:kml="http://www.opengis.net/kml"
> xmlns:atom="http://www.w3.org/2005/Atom"
> xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
> targetNamespace="http://www.google.com/kml/ext"
> elementFormDefault="qualified" version="090102 BETA"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
> ecore:ignoreSubstitutionGroups="true">
>
> <simpleType name="altitudeModeEnumType" ecore:enum="false" >
> <restriction base="string">
> <enumeration value="clampToSeaFloor"/>
> <enumeration value="relativeToSeaFloor"/>
> </restriction>
> </simpleType>
Wouldn't it be nicer if this actually restricted kml:altitudeModeGroup
rather than directly restricting string again?
>
> <element name="altitudeMode" type="gx:altitudeModeEnumType"
> substitutionGroup="kml:altitudeModeGroup"/>
>
> Usage in a file, note the gx:altitudeMode:
> <?xml version="1.0" encoding="UTF-8"?>
> <kml xmlns="http://earth.google.com/kml/2.2"
> xmlns:gx="http://www.google.com/kml/ext/2.2">
> <Document>
> <name>Kelly5m_Rugosity_1_1_1.kml</name>
> <GroundOverlay>
> <gx:altitudeMode>clampToSeaFloor</gx:altitudeMode>
> <drawOrder>20</drawOrder>
> <name>Kelly5m_Rugosity_1_1_1.tif</name>
> <Icon>
> <href>Kelly5m_Rugosity_1_1_1.tif</href>
> </Icon>
> <LatLonBox>
> <north>51.04529905</north>
> <south>50.99906962</south>
> <east>-121.7097378</east>
> <west>-121.7845071</west>
> </LatLonBox>
> </GroundOverlay>
> </Document>
> </kml>
>
> So I had created my kml genmodel / ecore files before I was aware of
> the gx extensions. Subsequently I created ext.genmodel and ext.ecore
> files which link to the kml.ecore and other ecore files, and generated
> new code.
>
> I set up the ResourceSet roughly as follows:
> resourceSet.getResourceFactoryRegistry().getExtensionToFacto
> ryMap().put(KML, new ExtResourceFactoryImpl());
> resourceSet.getPackageRegistry().put("http://www.google.com/kml/ext/2.2",
> ExtPackage.eINSTANCE);
ExtPackage.eNS_URI is equal to this string literal?
> resourceSet.getPackageRegistry().put("http://earth.google.com/kml/2.2",
> KmlPackage.eINSTANCE);
>
> So the Ext (google extension) support should extend the kml loading.
> Now with the new ecore:enum="false" in the schema, there is no longer
> an enum or class generated at all for the AltitudeModeEnumType.
>
> Now, the DocumentRoot in the kml package has:
> public String getAltitudeMode() {
> return
> (String)getMixed().get(KmlPackage.Literals.DOCUMENT_ROOT__AL
> TITUDE_MODE, true);
> }
>
> and
> public EObject getAltitudeModeGroup() {
> return
> (EObject)getMixed().get(KmlPackage.Literals.DOCUMENT_ROOT__A
> LTITUDE_MODE_GROUP, true);
> }
>
> as does the DocumentRoot in the ext package:
> public String getAltitudeMode() {
> return
> (String)getMixed().get(ExtPackage.Literals.DOCUMENT_ROOT__AL
> TITUDE_MODE, true);
> }
> (and hmm ... I'm thinking that having 4 different DocumentRoot classes
> defined is probably a problem).
>
> So the GroundOverlayType defined in kml now has this:
> public EObject getAltitudeModeGroup() {
> return altitudeModeGroup;
> }
>
> Hm. So that was a lot of detailed information yet still not a nice
> simple example.
Not so much. I guess the picture would be much simplified if you changed
<element name="altitudeModeGroup" abstract="true"/>
to include type="xsd:string" given that in both substitution group cases
you're dealing with subtypes of xsd:string.
> I guess the question is, what SHOULD I be doing to set up the
> resource so that a GroundOverlayType defined within the kml package
> will know to use the ext package to read something that has gx: in it
> (see above kml). It should now be possible to substitute them since
> they are not enums.
It looks like you've done the right registrations already...
>
> Thank you
>
> Tamar
>
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| |
Goto Forum:
Current Time: Wed Sep 25 13:03:51 GMT 2024
Powered by FUDForum. Page generated in 0.04822 seconds
|