Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc) » Get namespaces used in xml file
|
Re: Get namespaces used in xml file [message #872966 is a reply to message #872854] |
Thu, 17 May 2012 07:38 |
Ed Merks Messages: 33216 Registered: July 2009 |
Senior Member |
|
|
Comments below.
On 17/05/2012 2:30 AM, h3llghost wrote:
> Hello,
>
> I am searching for a possibility to read the namespaces out of xml
> file. I want to know, which are included and show different editors
> depending on the namespaces.
This is a problem we needed to address to support resource factory
registration based on content type where the content type is determined
by the namespace of the root element.
>
> Here is the root element of my xml file:
> <container:Container xmi:version="2.0"
> xmlns:xmi="hXXp://www.omg.org/XMI"
> xmlns:xsi="hXXp://www.w3.org/2001/XMLSchema-instance"
> xmlns:container="model.container" xmlns:dijkstra="model.dijkstra">
>
> I am using an ecore model and generated the model files.
>
> My first approach was with the help of the given methods of the
> ContainerImpl, but I didn't find anything, which helped me.
For any EObject, x, x.eClass().getEPackage().getNsURI() returns the
namespace of the class's package.
> So I used the Resource of the container (XMLResource), but nothing found.
> I found the XMLHelper so I tried it with it. The method
> getExtendedMetaData seems very interesting, but the return value is null.
>
> I have searched a lot with Google, but no real helpful solutions found.
What I think you're asking for is support for content-type registered
editors and resource factories. The generator will produce that for
you. In the Generator you can do this via the GenPackage property for
"Content Type Identifier". You'd set it to something like the qualified
package name, e.g., org.example.library. Be sure to delete all your
plugin.xmls and then regenerate. You'll see that the resource factory
will be registered a content-type-based registration and same for the
editor's registration. To determine the content type of the resource,
EMF will use a light-weight SAX parser to scan the root element,
determine it's namespace, and use that to determine the content type.
From that it will be able to use your registered resource factory to
parse the contents and the editor will only open for resource with that
content type. This is particularly useful if you have several models
that use the same file extension, e.g., *.xml is heavily used so must
use this content type mechanism..
>
> Thanks for any hints.
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Re: Get namespaces used in xml file [message #873200 is a reply to message #872966] |
Thu, 17 May 2012 17:07 |
John M. Messages: 198 Registered: July 2010 |
Senior Member |
|
|
Thanks for your fast answer. I have just changed the properties in the genmodel, but how can I use now that property?
I don't understand how I can access the content type from the source code.
I just create a ResourceSet and get the Resource, that one I cast to my Container.
But how get now the content types?
Is it enought to generate the model code or do I need more code?
In the case of the Container I have generated the edit and editor code, too.
[Updated on: Thu, 17 May 2012 17:07] Report message to a moderator
|
|
| | | | | |
Re: Get namespaces used in xml file [message #873595 is a reply to message #873586] |
Fri, 18 May 2012 16:07 |
John M. Messages: 198 Registered: July 2010 |
Senior Member |
|
|
My resource is from type XMIResourceImpl and I don't get any EObject from getAllContents.
The given TreeIterator is empty.
I think there must be at least the container in there.
It seems that I have missed something, haven't I?
I have added the content type identfier, delete the model plugin.xml and regenerated the model code.
The same I have done for the editor and edit source code.
I attached the model structure for better comprehension.
[Updated on: Fri, 18 May 2012 16:07] Report message to a moderator
|
|
| | | |
Re: Get namespaces used in xml file [message #874296 is a reply to message #874016] |
Sun, 20 May 2012 12:39 |
John M. Messages: 198 Registered: July 2010 |
Senior Member |
|
|
I don't want to annoy you, but I can't figure out the solution and I want to know what I am doing wrong. I am very grateful for your patience and advices.
I am really new to EMF and use the book EMF - Eclipse Modeling Framework, but such a specific case isn't covered by that book.
>> No, getContents returns an object from ContainerImpl.
> Then I'd expect the getAllContents iterator to iterate at least over that...
The ContainerImpl is a class generated out of my model and doesn't provide that method.
> I'm sure that if there is a root object, the iterator will yield at
> least that one as well as all the contained objects under it. So I
> think you have all the answers you need.
Yeah sure, but where is it?
The ContainerImpl is in general the root element, but doesn't provide the methods I need.
I hope attaching my models and genmodels helps to get more advices.
Perhaps there is a modeling issue.
Looking through the genmodel I noticed, that there is a fileextnsion property,
but it seems that it makes no difference.
The newest xml file looks like following:
<?xml version="1.0" encoding="UTF-8"?>
<container:Container xmi:version="2.0" xmlns:xmi="hXXp://www.omg.org/XMI" xmlns:xsi="hXXp://www.w3.org/2001/XMLSchema-instance" xmlns:bellmanford="de.tit09.fms.algos.model.bellmanford" xmlns:container="de.tit09.fms.algos.model.container" xmlns:dijkstra="de.tit09.fms.algos.model.dijkstra">
Now each namespace is correctly displayed compared to my start post.
EDIT:
But I found now a big issue with the Content Type Identifier in my case.
If I open a model file and I don't have all ecore models loaded in example the plugin isn't available. I got a PackageNotFoundException. You can open the file in the second try, but if you edit the values and save them all values from the "not found" model are removed, there is only the main tag.
I think there is some option missing for the handler. I have tried the same option, which I used for the ExtensionToFactoryMap, but it doesn't work for the ContentTypeToFactoryMap.
EDIT²:
I have done some research and a reasonable possibility could be that the order of ContentTypeToFactoryMap is different in comparison to ExtensionToFactoryMap. That means the * entry isn't at the first position.
Manual ordering of the entries for example with a LinkedHashMap isn't possible.
A working way is to clear the ContentTypeToFactoryMap and only add the * entry.
But I can't believe that the solution is a good one.
-
Attachment: models.zip
(Size: 5.17KB, Downloaded 222 times)
[Updated on: Sun, 20 May 2012 15:33] Report message to a moderator
|
|
|
Re: Get namespaces used in xml file [message #874333 is a reply to message #874296] |
Sun, 20 May 2012 15:30 |
Ed Merks Messages: 33216 Registered: July 2009 |
Senior Member |
|
|
Comments below.
On 20/05/2012 2:39 PM, h3llghost wrote:
> I don't want to annoy you, but I can't figure out the solution and I want to know what I am doing wrong. I am very grateful for your patience and advices.
> I am really new to EMF and use the book EMF - Eclipse Modeling Framework, but such a specific case isn't covered by that book.
>
>>> No, getContents returns an object from ContainerImpl.
>> Then I'd expect the getAllContents iterator to iterate at least over that...
> The ContainerImpl is a class generated out of my model and doesn't provide that method.
It's Resource.getAllContents. Each EObject also has eAllContents. It's
an iterator. You use it in a for loop. In both cases, it walks all the
contained objects...
>
>> I'm sure that if there is a root object, the iterator will yield at
>> least that one as well as all the contained objects under it. So I
>> think you have all the answers you need.
> Yeah sure, but where is it?
> The ContainerImpl is in general the root element, but doesn't provide the methods I need.
Container.eClass().getEPackage().getNsURI gives you the namespace of the
root object. You need to traverse the other objects if you want to know
all the namespaces.
>
> I hope attaching my models and genmodels helps to get more advices.
The answers to your questions are generic. They don't involve any
model-specific generated APIs.
> Perhaps there is a modeling issue.
>
> Looking through the genmodel I noticed, that there is a fileextnsion property,
> but it seems that it makes no difference.
It does, but as before, the plugin.xml doesn't regenerate once it exists.
>
> The newest xml file looks like following:
> <?xml version="1.0" encoding="UTF-8"?>
> <container:Container xmi:version="2.0" xmlns:xmi="hXXp://www.omg.org/XMI" xmlns:xsi="hXXp://www.w3.org/2001/XMLSchema-instance" xmlns:bellmanford="de.tit09.fms.algos.model.bellmanford" xmlns:container="de.tit09.fms.algos.model.container" xmlns:dijkstra="de.tit09.fms.algos.model.dijkstra">
Presumably there are other models involved in the serialization;
otherwise you'd not need/have the other xmlns declarations.
>
> Now each namespace is correctly displayed compared to my start post.
Do again, Resource.getAllContents yields an iterator you can use in a
for loop to visit all the contained objects in the resource. Can you
confirm that it yields the Container at least?
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Re: Get namespaces used in xml file [message #874336 is a reply to message #874333] |
Sun, 20 May 2012 15:43 |
John M. Messages: 198 Registered: July 2010 |
Senior Member |
|
|
> It's Resource.getAllContents. Each EObject also has eAllContents. It's
> an iterator. You use it in a for loop. In both cases, it walks all the
> contained objects...
Resource.getAllContents returns an object of the ContainerImpl.
ContainerImpl.eAllContents returns nothing.
> Container.eClass().getEPackage().getNsURI gives you the namespace of the
> root object. You need to traverse the other objects if you want to know
> all the namespaces.
Alright that is possible, but first I need the other objects.
Or do you mean, that I shall go recursive through my objects with eContents()?
>> Looking through the genmodel I noticed, that there is a fileextnsion property,
>> but it seems that it makes no difference.
> It does, but as before, the plugin.xml doesn't regenerate once it exists.
I always delete the model plugin.xml and the only difference is that the
file extension is set to the attribute.
I can't say that something else changed in the behaviour of the system.
Finally it must be the extension of the "container"?
The ContainerImpl is saved as .container and all other models are contained.
> Presumably there are other models involved in the serialization;
> otherwise you'd not need/have the other xmlns declarations.
Correct, because the model delievers an "extension point".
There is the basemodel and our models can extend that one.
> Do again, Resource.getAllContents yields an iterator you can use in a
> for loop to visit all the contained objects in the resource. Can you
> confirm that it yields the Container at least?
Resource.getAllContents returns an object of the ContainerImpl.
But I found now a big issue with the Content Type Identifier in my case.
If I open a model file and I don't have all ecore models loaded in example
the plugin isn't available. I got a PackageNotFoundException. You can
open the file in the second try, but if you edit the values and save them
all values from the "not found" model are removed, there is only the main tag.
I think there is some option missing for the handler. I have tried the same
option, which I used for the ExtensionToFactoryMap, but it doesn't work for
the ContentTypeToFactoryMap.
I have done some research and a reasonable possibility could be that the order
of ContentTypeToFactoryMap is different in comparison to ExtensionToFactoryMap.
That means the * entry isn't at the first position.
Manual ordering of the entries for example with a LinkedHashMap isn't possible.
A working way is to clear the ContentTypeToFactoryMap and only add the * entry.
But I can't believe that the solution is a good one.
[Updated on: Mon, 21 May 2012 00:09] Report message to a moderator
|
|
|
Re: Get namespaces used in xml file [message #874605 is a reply to message #874336] |
Mon, 21 May 2012 08:30 |
Ed Merks Messages: 33216 Registered: July 2009 |
Senior Member |
|
|
Comments below.
On 20/05/2012 5:43 PM, h3llghost wrote:
>> It's Resource.getAllContents. Each EObject also has eAllContents. It's
>> an iterator. You use it in a for loop. In both cases, it walks all the
>> contained objects...
> Resource.getAllContents returns an object of the ContainerImpl.
Yes, the root objects of the resource.
> ContainerImpl.eAllContents returns nothing.
So your container doesn't actually contain (via containment references)
at this point.
>
>> Container.eClass().getEPackage().getNsURI gives you the namespace of the
>> root object. You need to traverse the other objects if you want to know
>> all the namespaces.
> Alright that is possible, but first I need the other objects. :)
Object's referenced by non-containment might result in namespace
declarations as well, if their xsi:type or xmi:type is needed in the
serialization (which is the case if the referencing feature's type is
abstract and the object is of some derived type). You can determine all
the object referenced via non-containment with
EObject.eCrossReferences(). So for each EObject you visit in
Resource.getAllContents() you can also visit that object's eCrossReferences.
>
>>> Looking through the genmodel I noticed, that there is a fileextnsion
>>> property,
>>> but it seems that it makes no difference.
>> It does, but as before, the plugin.xml doesn't regenerate once it
>> exists.
> I always delete the model plugin.xml and the only difference is that the
> file extension is set to the attribute.
Now you say there is a difference. That's the opposite of it makes no
difference...
> I can't say that something else changed in the behaviour of the system.
> Finally it must be the extension of the "container"?
It must be the extension of the names of the resource you intend to
process with that resource factory.
> The ContainerImpl is saved as .container and all other models are
> contained.
Though apparently not according your comment about eAllContents being
empty for your Container.
>
>> Presumably there are other models involved in the serialization;
>> otherwise you'd not need/have the other xmlns declarations.
> Correct, because the model delievers an "extension point".
> There is the basemodel and our models can extend that one.
>
>> Do again, Resource.getAllContents yields an iterator you can use in a
>> for loop to visit all the contained objects in the resource. Can you
>> confirm that it yields the Container at least?
> Resource.getAllContents returns an object of the ContainerImpl.
>
>
> But I found now a big issue with the Content Type Identifier in my case.
> If I open a model file and I don't have all ecore models loaded in
> example
> the plugin isn't available.
Yes, all models must be registered. In an Eclipse environment that
won't be a problem because they're registered in their plugin.xml and
those registrations will be globally available.
> I got a PackageNotFoundException. You can
> open the file in the second try, but if you edit the values and save them
> all values from the "not found" model are removed, there is only the
> main tag.
> I think there is some option missing for the handler. I have tried the
> same
> option, which I used for the ExtensionToFactoryMap, but it doesn't
> work for
> the ContentTypeToFactoryMap.
The problem sounds like one of models that aren't registered.
Presumably you've generated these other models and they have plugin.xml
registrations. (If you have all your models in one bundle, you should
have only a single *.genmodel for all your packages, not multiple).
>
> I have done some research and a reasonable possibility could be that
> the order
> of ContentTypeToFactoryMap is different in comparison to
> ExtensionToFactoryMap.
Your generated registration should appear only for the content type, not
the extension, right? Position won't matter for that.
> That means the * entry isn't at the first position.
> Manual ordering of the entries for example with a LinkedHashMap isn't
> possible.
> A working way is to clear the ContentTypeToFactoryMap and only add the
> * entry.
> But I can't believe that the solution is a good one.
There must be details you're leaving out. You can't register more than
one factory for the same extension; you'll see problems about that in
the error log. And for content types, it's their content type
identifier that's registered. All resources with the content type's
extension will be analyzed to see if they content your content type's
type of content.
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Re: Get namespaces used in xml file [message #874658 is a reply to message #874605] |
Mon, 21 May 2012 10:24 |
John M. Messages: 198 Registered: July 2010 |
Senior Member |
|
|
So finally I got the getAllContents working.
It was a mistake in understanding the syso output in eclipse.
Because the output was [] I thought the iterator is empty, after more investigation
with the help of the debugger in eclipse I see that there are elements in the iterator.
>> But I found now a big issue with the Content Type Identifier in my case.
>> If I open a model file and I don't have all ecore models loaded in
>> example
>> the plugin isn't available.
> Yes, all models must be registered. In an Eclipse environment that
> won't be a problem because they're registered in their plugin.xml and
> those registrations will be globally available.
It is possible that not all model plugins are available, because it should
be an extensible application, where others can provide new model parts or plugins.
That is the reason, why I have a own genmodel for each model, see the attached model.zip
(hXXp://www.eclipse.org/forums/index.php/fa/9794/).
>> That means the * entry isn't at the first position.
>> Manual ordering of the entries for example with a LinkedHashMap isn't
>> possible.
>> A working way is to clear the ContentTypeToFactoryMap and only add the
>> * entry.
>> But I can't believe that the solution is a good one.
> There must be details you're leaving out. You can't register more than
> one factory for the same extension; you'll see problems about that in
> the error log. And for content types, it's their content type
> identifier that's registered. All resources with the content type's
> extension will be analyzed to see if they content your content type's
> type of content.
There are no errors in the log, otherwise I would react on them.
I have removed all file extensions expect for the container model.
But the problem with the PackageNotFoundException still remains.
I can't fix it with the following code:
Resource.Factory.Registry.INSTANCE.getContentTypeToFactoryMap().put("*", new EcoreResourceFactoryImpl() {
@Override
public Resource createResource(URI uri) {
XMIResourceImpl resource = (XMIResourceImpl) super.createResource(uri);
resource.getDefaultLoadOptions().put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
return resource;
}
});
My workaround is to clear that list and only add the * entry.
But it doesn't seem correct.
Looking in the keyset of the content types shows that all plugins,
which are available, and additional the * entry is shown.
Basically my idea is to provide a model, which can be simple extended by
other people and they can share their work in own plugins.
That is the reason why I can't be sure that all plugins are always
available.
> In the Generator you can do this via the GenPackage property for
> "Content Type Identifier". You'd set it to something like the qualified
> package name, e.g., org.example.library
What does the package name mean?
Must it be the plugin id or the Ns Uri of my model?
Which file extension shall be used for the contained models, which are
holded by the main container model?
[Updated on: Mon, 21 May 2012 13:13] Report message to a moderator
|
|
|
Re: Get namespaces used in xml file [message #874844 is a reply to message #874658] |
Mon, 21 May 2012 16:38 |
Ed Merks Messages: 33216 Registered: July 2009 |
Senior Member |
|
|
Comments below.
On 21/05/2012 12:24 PM, h3llghost wrote:
> So finally I got the getAllContents working.
> It was a mistake in understanding the syso output in eclipse.
> Because the output was [] I thought the iterator is empty, after more
> investigation
> with the help of the debugger in eclipse I see that there are elements
> in the iterator.
I figured this must be working properly.
>
>>> But I found now a big issue with the Content Type Identifier in my
>>> case.
>>> If I open a model file and I don't have all ecore models loaded in
>>> example
>>> the plugin isn't available.
>> Yes, all models must be registered. In an Eclipse environment that
>> won't be a problem because they're registered in their plugin.xml and
>> those registrations will be globally available.
> It is possible that not all model plugins are available, because it
> should
> be an extensible application, where others can provide new model parts
> or plugins.
> That is the reason, why I have a own genmodel for each model, see the
> attached model.zip
> (hXXp://www.eclipse.org/forums/index.php/fa/9794/).
They'll need to be available when you read documents that rely on them
for the content they contain.
>
>>> That means the * entry isn't at the first position.
>>> Manual ordering of the entries for example with a LinkedHashMap isn't
>>> possible.
>>> A working way is to clear the ContentTypeToFactoryMap and only add the
>>> * entry.
>>> But I can't believe that the solution is a good one.
>> There must be details you're leaving out. You can't register more than
>> one factory for the same extension; you'll see problems about that in
>> the error log. And for content types, it's their content type
>> identifier that's registered. All resources with the content type's
>> extension will be analyzed to see if they content your content type's
>> type of content.
> There are no errors in the log, otherwise I would react on them.
> I have removed all file extensions expect for the container model.
> But the problem with the PackageNotFoundException still remains.
That's a missing package problem.
>
> I can't fix it with the following code:
> Resource.Factory.Registry.INSTANCE.getContentTypeToFactoryMap().put("*",
> new EcoreResourceFactoryImpl() {
> @Override
> public Resource createResource(URI uri) {
> XMIResourceImpl resource = (XMIResourceImpl)
> super.createResource(uri);
>
> resource.getDefaultLoadOptions().put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE,
> Boolean.TRUE);
> return resource;
> }
> });
> My workaround is to clear that list and only add the * entry.
So you're not using the generated resource factory.
> But it doesn't seem correct.
>
> Basically my idea is to provide a model, which can be simple extended by
> other people and they can share their work in own plugins.
> That is the reason why I can't be sure that all plugins are always
> available.
So the option you're using above will help...
>
>> In the Generator you can do this via the GenPackage property for
>> "Content Type Identifier". You'd set it to something like the qualified
>> package name, e.g., org.example.library
> What does the package name mean?
It must be a unique identifier.
> Must it be the plugin id or the Ns Uri of my model?
No, it just has to be unique. It should be an identifier, not a URI.
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Goto Forum:
Current Time: Mon Sep 23 01:19:47 GMT 2024
Powered by FUDForum. Page generated in 0.05144 seconds
|