Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Customization of XML serialization
Customization of XML serialization [message #645037] Wed, 15 December 2010 10:19 Go to next message
Martin Zatopek is currently offline Martin ZatopekFriend
Messages: 5
Registered: December 2010
Junior Member
Hi all,

now I am investigating possibilities of customization of XML serialization. I have found the possibility to change name of an element or persist an XML attribute as a nested element. Now I am curious if I can save an element as an attribute. For example, my model contains two classes - Phase and ExInteger (I need to manage this integer as a class, since its definition is common string, which can be interpreted as an integer). My ecore specification looks like:

  <eClassifiers xsi:type="ecore:EClass" name="Phase">
    <eStructuralFeatures xsi:type="ecore:EReference" name="number" eType="#//ExInteger"
        containment="true" resolveProxies="false">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData"> //this is useless attempt to achieve the desired behaviour
        <details key="kind" value="attribute"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>


And the ExInteger class contains only one single string attribute (plus few custom operations). So the default XML looks like this:

<phase>
  <number stringValue="123"/>
</phase>


The desired XML would be:

<phase number="123">
</phase>


Do I have a chance to achieve this behaviour?

Thank a lot for any suggestion, Martin.
Re: Customization of XML serialization [message #645152 is a reply to message #645037] Wed, 15 December 2010 17:01 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Martin,

Comments below.


Martin Zatopek wrote:
> Hi all,
>
> now I am investigating possibilities of customization of XML
> serialization. I have found the possibility to change name of an
> element or persist an XML attribute as a nested element. Now I am
> curious if I can save an element as an attribute. For example, my
> model contains two classes - Phase and ExInteger (I need to manage
> this integer as a class, since its definition is common string, which
> can be interpreted as an integer).
It sounds more likely that it should be a specialized data type.
> My ecore specification looks like:
>
>
> <eClassifiers xsi:type="ecore:EClass" name="Phase">
> <eStructuralFeatures xsi:type="ecore:EReference" name="number"
> eType="#//ExInteger"
> containment="true" resolveProxies="false">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData"> //this
> is useless attempt to achieve the desired behaviour
> <details key="kind" value="attribute"/>
> </eAnnotations>
> </eStructuralFeatures>
> </eClassifiers>
>
>
> And the ExInteger class contains only one single string attribute
> (plus few custom operations). So the default XML looks like this:
>
>
> <phase>
> <number stringValue="123"/>
> </phase>
>
>
> The desired XML would be:
>
>
> <phase number="123">
> </phase>
>
>
> Do I have a chance to achieve this behaviour?
I don't see any strong reason why you'd model ExInteger as an EClass.
Can you give any?

If there is a good reason, you could make the EReference transient and
derived, define an EDataType that wraps the generated interface for
ExInteger, and define an EAttribute that isn't transient for storing the
actual value... You could suppress the accessors for it from the API.
>
> Thank a lot for any suggestion, Martin.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Customization of XML serialization [message #645422 is a reply to message #645152] Fri, 17 December 2010 09:00 Go to previous messageGo to next message
Martin Zatopek is currently offline Martin ZatopekFriend
Messages: 5
Registered: December 2010
Junior Member
Thank a lot, Ed. I really appreciate your answer. And that was great support from your side!

I would like to have the ExInteger object part of emf model, since the value resolution (ExInteger -> Integer) is based on data somewhere in the model. The context where the ExInteger is placed in the model hierarchy (for example eContainer reference) would be really appreciated.

Thanks for your suggestion how to work around and achieve desired behaviour, but for now I would like to avoid the change of the model in order to have just a nice XML.

Thanks again, Martin.
Re: Customization of XML serialization [message #645437 is a reply to message #645037] Fri, 17 December 2010 09:24 Go to previous messageGo to next message
Martin Zatopek is currently offline Martin ZatopekFriend
Messages: 5
Registered: December 2010
Junior Member
I have another question. It is still concerned in 'Customization of XML serialization' I decided to use this thread again.

I would like to use non-default XML elements naming convention. I found that is possible to do by ecore annotations. I tied to simplify the issue as more as possible. Consider following simple ecore file (two classes Root and Child, Root class has one reference called children to Child class and Child class has one simple string attribute 'value'):

<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model"
    nsURI="clover" nsPrefix="clover">
  <eClassifiers xsi:type="ecore:EClass" name="Root">
    <eStructuralFeatures xsi:type="ecore:EReference" name="children" upperBound="-1"
        eType="#//Child" containment="true" resolveProxies="false">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="name" value="child"/>
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Child">
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
  </eClassifiers>
</ecore:EPackage>


Take a note of annotation. Children reference should be persisted in XML element called 'child'.

Here is the code which use generated model. First creates root class with single child and saves it into a file.

public class Test {
	private static void save() throws IOException {
		ResourceSet resourceSet = new ResourceSetImpl();
		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMLResourceFactoryImpl());
		ModelPackageImpl.eINSTANCE.eClass();
		
		Resource graphResource = resourceSet.createResource(URI.createFileURI("c:/Kokon/work/temp/junk/simple.xml"));
		ModelFactory modelFactory = ModelFactory.eINSTANCE;

		//create model
		Root root = modelFactory.createRoot();
		
		Child child = modelFactory.createChild();
		child.setValue("kokon");
		
		root.getChildrens().add(child);
		
		graphResource.getContents().add(root);
		
		Map options = new HashMap();
		options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
		
		graphResource.save(options);
	}

	private static void load() throws IOException {
		ResourceSet resourceSet = new ResourceSetImpl();
		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMLResourceFactoryImpl());
		ModelPackageImpl.eINSTANCE.eClass();
		
		Resource graphResource = resourceSet.createResource(URI.createFileURI("c:/Kokon/work/temp/junk/simple.xml"));
		ModelFactory modelFactory = ModelFactory.eINSTANCE;


		Map options = new HashMap();
		options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
		
		graphResource.load(options);
		
		System.out.println(graphResource.getContents().get(0));
	}

	public static void main(String[] args) throws IOException {
		save();
		load();
	}
}


The resulted XML file looks perfect ('child' element instead of 'children'):

<?xml version="1.0" encoding="ASCII"?>
<clover:Root xmlns:clover="clover">
  <child value="kokon"/>
</clover:Root>


But when I try to load the XML file again I got the following exception:

Exception in thread "main" org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Feature 'child' not found. (file:/c:/Kokon/work/temp/junk/simple.xml, 3, 25)
	at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.handleErrors(XMLLoadImpl.java:83)
	at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.load(XMLLoadImpl.java:191)
	at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doLoad(XMLResourceImpl.java:180)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1494)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1282)
	at Test.load(Test.java:55)
	at Test.main(Test.java:62)
Caused by: org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'child' not found. (file:/c:/Kokon/work/temp/junk/simple.xml, 3, 25)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.reportUnknownFeature(XMLHandler.java:1991)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleUnknownFeature(XMLHandler.java:1955)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleFeature(XMLHandler.java:1899)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.processElement(XMLHandler.java:1023)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:1001)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:712)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
	at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1339)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2747)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
	at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.load(XMLLoadImpl.java:181)
	... 5 more


What is wrong in my Test class?

Thanks again for your time! Martin
Re: Customization of XML serialization [message #645440 is a reply to message #645037] Fri, 17 December 2010 09:27 Go to previous messageGo to next message
Martin Zatopek is currently offline Martin ZatopekFriend
Messages: 5
Registered: December 2010
Junior Member
BTW I was able to customize XMLSaveImpl so that ExInteger class is saved as attribute. And I am going to try to do the same thing with XMLLoadImpl, but I run into another issue described above.
Re: Customization of XML serialization [message #645486 is a reply to message #645437] Fri, 17 December 2010 12:42 Go to previous messageGo to next message
Martin Zatopek is currently offline Martin ZatopekFriend
Messages: 5
Registered: December 2010
Junior Member
I found the solution Smile After few hours of debugging I add one more annotation into my ecore file:

<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model"
    nsURI="clover" nsPrefix="clover">
  <eClassifiers xsi:type="ecore:EClass" name="Root">
    <eStructuralFeatures xsi:type="ecore:EReference" name="children" upperBound="-1"
        eType="#//Child" containment="true" resolveProxies="false">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="name" value="child"/>
        [B]<details key="kind" value="element"/>[/B]
      </eAnnotations>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Child">
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
  </eClassifiers>
</ecore:EPackage>


Thanks anyway and I'm sorry for these useless posts.

Martin

PS: are the annotations described somewhere in detail?
Re: Customization of XML serialization [message #645566 is a reply to message #645422] Sat, 18 December 2010 01:39 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Martin,

Comments below.

Martin Zatopek wrote:
> Thank a lot, Ed. I really appreciate your answer. And that was great
> support from your side!
>
> I would like to have the ExInteger object part of emf model, since the
> value resolution (ExInteger -> Integer) is based on data somewhere in
> the model. The context where the ExInteger is placed in the model
> hierarchy (for example eContainer reference) would be really appreciated.
I wonder though the relationship when you deserialize.
>
> Thanks for your suggestion how to work around and achieve desired
> behaviour, but for now I would like to avoid the change of the model
> in order to have just a nice XML.
You could make all the changes invisible in the API...
>
> Thanks again, Martin.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Customization of XML serialization [message #645567 is a reply to message #645486] Sat, 18 December 2010 01:41 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Martin,

The book describes all the annotations produce for XML Schema...


Martin Zatopek wrote:
> I found the solution :) After few hours of debugging I add one more
> annotation into my ecore file:
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <ecore:EPackage xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model"
> nsURI="clover" nsPrefix="clover">
> <eClassifiers xsi:type="ecore:EClass" name="Root">
> <eStructuralFeatures xsi:type="ecore:EReference" name="children"
> upperBound="-1"
> eType="#//Child" containment="true" resolveProxies="false">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="child"/>
> <details key="kind" value="element"/>
> </eAnnotations>
> </eStructuralFeatures>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Child">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="value"
> eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> </ecore:EPackage>
>
>
> Thanks anyway and I'm sorry for these useless posts.
>
> Martin
>
> PS: are the annotations described somewhere in detail?


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:[EMF compare] An Extensible Framework
Next Topic:knowing the get/set method names of an attribute
Goto Forum:
  


Current Time: Wed Apr 24 13:46:20 GMT 2024

Powered by FUDForum. Page generated in 0.03573 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top