Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Programatically edit XML Schema file(Programatically edit (read/modify/write) a .xsd file within a generic eclipse project)
Programatically edit XML Schema file [message #1828586] Sat, 13 June 2020 15:32 Go to next message
Sergio Panico is currently offline Sergio PanicoFriend
Messages: 3
Registered: June 2020
Junior Member
Hi guys,
I'm developing an eclipse plugin to automate some boring and time-consuming activities in creating a specific eclipse project for my company.

My need is to programatically edit (hence read, modify and write back) an .xsd file inside a project in my workspace.
I read a lot of material and searched the net about this but I've not found anything complete.

What is the best way to do this with Eclipse 4.2.2.?

I read here about how to use ECore to "parse" a XML Schema with something like this:

	private Collection<EObject> readEObjectsFromResource(IFile xsdFile){
		XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder();
		return xsdEcoreBuilder.generate(URI.createFileURI(xsdFile.getLocation().toString()));
	}


But I didn't understood how to alter the schema (add/del elements or change target namespace and so on)

Could you guys please give me help to achieve this?

Sorry if this post could be OT, in this case i'd ask you to address me to the correct forum.

Thanks a lot
Bye
Sergio
Re: Programatically edit XML Schema file [message #1828589 is a reply to message #1828586] Sat, 13 June 2020 19:16 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 31841
Registered: July 2009
Senior Member
What you show above its only useful for converting an XSD model to and Ecore model. If you want to edit/modify an XML Schema you could use the XSD model directly:

https://wiki.eclipse.org/MDT-XSD-FAQ



Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Programatically edit XML Schema file [message #1828597 is a reply to message #1828589] Sun, 14 June 2020 08:48 Go to previous messageGo to next message
Sergio Panico is currently offline Sergio PanicoFriend
Messages: 3
Registered: June 2020
Junior Member
Hi Ed,
I will try this approach. Thanks fot this hint.

Sergio
Re: Programatically edit XML Schema file [message #1828878 is a reply to message #1828586] Sat, 20 June 2020 21:43 Go to previous messageGo to next message
Sergio Panico is currently offline Sergio PanicoFriend
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 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 31841
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/
Previous Topic:Split Ecore model over different repos
Next Topic:Save disabled
Goto Forum:
  


Current Time: Tue Apr 20 14:41:02 GMT 2021

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

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

Back to the top