I have a XSD-File, which I transformed into an ecore-model and from where I generated model code. Now i would like to load a xml-file for that schema, but keep getting the error:
org.eclipse.emf.ecore.xmi.PackageNotFoundException:
Package with uri 'null' not found.
(file:/C:/Users/mboeschen/safety/devel/eclipse_plugins...
/de.offis.etas.load/examples/minimal.xml, 2, 7)
As this is directly after the root tag in my xml file I suspect that something is going wrong after reading the root tag.
My code is the following:
public static void main(String[] args) throws IOException {
MinimalPackage.eINSTANCE.eClass();
MinimalPackage packageInstance = MinimalPackage.eINSTANCE;
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
Map<String, Object> m = reg.getExtensionToFactoryMap();
m.put("*", new XMLResourceFactoryImpl());
// Obtain a new resource set
ResourceSet resSet = new ResourceSetImpl();
resSet.setResourceFactoryRegistry(reg);
resSet.getPackageRegistry().put(MinimalPackage.eNS_URI,
MinimalPackage.eINSTANCE);
resSet.getPackageRegistry().put(null,
MinimalPackage.eINSTANCE);
// Get the resource
URI uri = URI
.createFileURI("C:/Users/mboeschen/safety/devel/eclipse_plugins...
/de.offis.etas.load/examples/minimal.xml");
Resource resource = resSet.getResource(uri, true);
RootType r = (RootType) resource.getContents().get(0);
System.out.println(r);
The schema file looks like this:
<?xml version="1.0" encoding="US-ASCII"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Inner" type="MyType">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="MyType">
<xs:sequence> </xs:sequence>
</xs:complexType>
</xs:schema>
And this is the xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Inner>
</Inner>
</Root>
Any ideas what is happening here? Any help appreciated!
In the last two years, I have refined the solution proposed by @Severin for my project. Therefore, I give an additional answer as follows:
When a resource is loaded via the XMLResource
, several helper classes are called to parse and map the XML to EMF/Ecore. Most of those classes can be replaced by changing the load options. There are several locations where this can be done:
ResourceSet
has default load optionsResource
default load options (which are typically set via the generated ResourceFactory
)Resource.load()
method can be provided with load optionsDepending on the access you have (your own generated code vs. 3rd party generated code) and the location/frequency where the resource is loaded, you need to use one of those alternatives to add to the load options.
Load options come as a key-value map. The keys are defined by constants in Resource
and XMLResource
, for example.
Two keys are of special interest for the problem described initially:
XMLResource.OPTION_MISSING_PACKAGE_HANDLER
provides a handler which is called if EMF cannot find a suitable EPackageXMLResource.OPTION_EXTENDED_META_DATA
yields either a boolean (indicating whether to use extended meta-data, usually true
), or a concrete instance of ExtendedMetaData
, which provides all kinds of mapping information between XML and Ecore.For simple cases, when
you can just give a MissingPackageHandler
implementation like this one:
MissingPackageHandler mph = new MissingPackageHandler() {
@Override
public EPackage getPackage(final String nsURI) {
return MyModelEPackage.eINSTANCE;
}
};
And at least in my project, I also needed to set this ExtendedMetaData
:
BasicExtendedMetaData bemd = new BasicExtendedMetaData(new EPackageRegistryImpl(EPackage.Registry.INSTANCE)) {
@Override
protected boolean isFeatureNamespaceMatchingLax() {
return true;
}
};
If more than one EPackage
s and namespaces are involved, then the MissingPackageHandler
might be too high-level and the distinction needs to be done directly by the ExtendedMetaData
implementation.
Following the answer of @Severin, this could be done like this:
BasicExtendedMetaData bemd = new BasicExtendedMetaData() {
private static final String NAMESPACE_GOOGLE_EXT_2_2 = "http://www.google.com/kml/ext/2.2";
private static final String NAMESPACE_OPENGIS_2_2 = "http://www.opengis.net/kml/2.2";
private static final String NAMESPACE_DEFAULT = NAMESPACE_OPENGIS_2_2;
@Override
public EPackage getPackage(String namespace) {
if(namespace==null) {
namespace = NAMESPACE_DEFAULT;
}
return super.getPackage(namespace);
}
@Override
public EStructuralFeature getElement(String namespace, String name) {
// try to find feature in OPENGIS package
EStructuralFeature result = super.getElement(NAMESPACE_OPENGIS_2_2, name);
if (feature == null) {
// if not found, try GOOGLE_EXT
feature = super.getElement(NAMESPACE_GOOGLE_EXT_2_2, name);
}
return feature;
}
});
When you generated your model, you probably got a generated [YourModelName]ResourceFactoryImpl class. I have experienced the same problem for my KML editor, that is how I solved it:
public class OgckmlResourceFactoryImpl extends ResourceFactoryImpl {
...
/**
* Creates an instance of the resource.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
@Override
public Resource createResource(URI uri) {
XMLResource result = new OgckmlResourceImpl(uri);
setupOptions(result);
return result;
}
protected void setupOptions(XMLResource result)
{
...
result.getDefaultLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, new BasicExtendedMetaData()
{
private static final String NAMESPACE_GOOGLE_EXT_2_2 = "http://www.google.com/kml/ext/2.2";
private static final String NAMESPACE_OPENGIS_2_2 = "http://www.opengis.net/kml/2.2";
private static final String NAMESPACE_DEFAULT = NAMESPACE_OPENGIS_2_2;
@Override
public EPackage getPackage(String namespace) {
if(namespace==null){
namespace = NAMESPACE_DEFAULT;
}
return super.getPackage(namespace);
}
@Override
public EStructuralFeature getElement(String namespace, String name)
{
if (feature == null)
feature = super.getElement(NAMESPACE_OPENGIS_2_2, name);
if (feature == null)
feature = super.getElement(NAMESPACE_GOOGLE_EXT_2_2, name);
return feature;
}
});
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With