|
Re: Customization of XML serialization [message #645152 is a reply to message #645037] |
Wed, 15 December 2010 17:01 |
Ed Merks 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 #645437 is a reply to message #645037] |
Fri, 17 December 2010 09:24 |
Martin Zatopek 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
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03573 seconds