|
|
|
Re: Programatically edit XML Schema file [message #1828878 is a reply to message #1828586] |
Sat, 20 June 2020 21:43 |
Sergio Panico Messages: 3 Registered: June 2020 |
Junior Member |
|
|
Hi guys,
I'm able to read/write the XSD as per Ed suggestions (thanks again) with something like this:
private XSDSchema loadXsdFromFile(IFile xsdFile)
throws IOException, CoreException {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE);
resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_PROGRESS_MONITOR, progressMonitor);
XSDResourceImpl xsdMainResource = (XSDResourceImpl) resourceSet
.createResource(URI.createURI("*.xsd"));
xsdMainResource.setURI(URI.createFileURI(xsdFile.getLocation()
.toString()));
xsdMainResource.load(xsdFile.getContents(),
resourceSet.getLoadOptions());
return xsdMainResource.getSchema();
}
private void writeXsdToFile(IFile xsdFile, XSDSchema xsdSchema) throws IOException {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE);
resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_PROGRESS_MONITOR, progressMonitor);
XSDResourceImpl xsdMainResource = (XSDResourceImpl) resourceSet
.createResource(URI.createURI("*.xsd"));
xsdMainResource.setURI(URI.createFileURI(xsdFile.getLocation()
.toString()));
xsdMainResource.getContents().add(xsdSchema);
xsdMainResource.save(Collections.EMPTY_MAP);
}
and hence edit the loaded xml schema with
private void consolidateXsd() throws CoreException, ClassNotFoundException,
InstantiationException, IllegalAccessException, ClassCastException,
IOException {
IFile xsdFile = myProject().getFile(new Path(myXsdFile + ".xsd"));
IFile xsdInlineSchemaFile = myProject().getFile(
new Path(myXsdFile + "_InlineSchema1.xsd"));
XSDSchema xsdSchema = loadXsdFromFile(xsdFile);
xsdSchema.setTargetNamespace(esbServiceContext.getNamespace());
//xsdSchema.getElementDeclarations().clear(); //this doesn't work :|
XSDSchema xsdInlineSchema = ((XSDSchemaDirectiveImpl) xsdSchema
.getContents().get(0)).getResolvedSchema();
xsdInlineSchema.getQNamePrefixToNamespaceMap().put("tns",
myContext.getNamespace());
xsdInlineSchema.setTargetNamespace(myContext.getNamespace());
xsdInlineSchema.getElementDeclarations().clear(); //this doesn't work, too :|
writeXsdToFile(xsdFile, xsdSchema);
writeXsdToFile(xsdInlineSchemaFile, xsdInlineSchema);
}
Is this the correct way or there is something better?
I mean... as my xsd have a reference to an inner schema (xsd:include) I understood the XSDSchema (loaded from the root xsd file) models any schema elements even if they belongs to the included (sub)schemas.
If this is right, why when I save the root schema the inner schema file is not get updated too?
For example, after saved (the root schema):
- when I update the target namespace on the root file, I was expected it will updated on the inner schema file, too. It is not.
- when I empty the elements declaration on the root file, I was expected it will cleaned on the inner schema file, too. It is not.
- to achieve this, i've to save and repeat all the ajustments in both the files (root and inner(s)) one by one. Is this right?
- why getElementDeclarations().clear() doesn't remove all the elements?
Moreover:
- after call writeXsdToFile the resource goes out-of-sync with the eclipse project. How can I avoid this?
Sorry if this is not so clear but I'm a bit confused as this is the first time i approaching with EMF/XSD.
Bye
Sergio
|
|
|
Re: Programatically edit XML Schema file [message #1828881 is a reply to message #1828878] |
Sun, 21 June 2020 05:31 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
This doesn't really look ideal. Typically you'll want to reuse a resource set, not create a new one for each resource you load, especially given that schemas can import/include other schemas such that the collection if interrelated schemas will all be loaded into one resource set in the end. In the FAQ it shows how to convert an IFile to a URI:
https://wiki.eclipse.org/EMF/FAQ#How_do_I_map_between_an_EMF_Resource_and_an_Eclipse_IFile.3F
So given you want to load a schema from an IFile, you should be able to use resourceSet.getResource(URI.createPlatformResourceURI(iFile.getFullPath().toString(), true), true) for that purpose, instead of "create with dummy URI", set physical URI location, followed by explicit load from a workspace stream.
Also, Resource has a org.eclipse.emf.ecore.resource.Resource.save(Map<?, ?>) method, so you can save the resource you've loaded previous back to where you loaded it from. There is also a org.eclipse.emf.ecore.resource.Resource.save(OutputStream, Map<?, ?>) method for "save as" to a different location. And of course you can use Resource.setURI to change the locate and save it to that location. The out-of-sync problem is because you are writing to the file location URI.createFileURI(xsdFile.getLocation().toString()), bypassing the workspace.
Given you don't show the schemas, it's hard to guess what you are expecting versus what's actually happening. Each schema has a separate target namespace so I would not expect change one schema's target namespace to affect another schema target namespace. And of course including a schema with no target namespace in a schema with a target namespace will logically map the including schema's target namespace on to the included schema.
In terms of editing, please read the Javadoc carefully:
EList<XSDElementDeclaration> org.eclipse.xsd.XSDSchema.getElementDeclarations()
Returns the value of the 'Element Declarations' reference list. The list contents are of type org.eclipse.xsd.XSDElementDeclaration.
This represents the element declarations infoset property. It is computed from the contents and should typically not be set directly. In the end, the XSD model is effectively two models in one. It is the concrete model of the underlying DOM representation of the XML Schema---this is the one you can actually edit and modify---as well as the logical "infoset" model described in the XML Schema specification. The specification describes how the concrete model is mapped to the local model and you can only "modify" the logical model by modifying the physical model. So when editing look for methods that say they are "concrete".
Look the Javadoc of following for an example of how to create a schema from scratch:
https://git.eclipse.org/c/xsd/org.eclipse.xsd.git/tree/plugins/org.eclipse.xsd/src/org/eclipse/xsd/util/XSDPrototypicalSchema.java
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Powered by
FUDForum. Page generated in 0.03611 seconds