Customization of XML serialization [message #645037] |
Wed, 15 December 2010 05:19  |
Eclipse User |
|
|
|
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 12:01   |
Eclipse User |
|
|
|
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.
|
|
|
|
Re: Customization of XML serialization [message #645437 is a reply to message #645037] |
Fri, 17 December 2010 04:24   |
Eclipse User |
|
|
|
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 #645567 is a reply to message #645486] |
Fri, 17 December 2010 20:41  |
Eclipse User |
|
|
|
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?
|
|
|
Powered by
FUDForum. Page generated in 0.09039 seconds