加载没有给定名称空间的XML作为EMF模型:“找不到包含uri'null'的包” - 例外

时间:2013-10-14 15:28:54

标签: java eclipse-emf

我有一个XSD文件,我将其转换为生态模型,并从中生成模型代码。现在我想为该架构加载一个xml文件,但不断收到错误:

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)

由于这是在我的xml文件中的根标记之后,我怀疑在读取根标记后出现了问题。

我的代码如下:

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);

架构文件如下所示:

<?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>

这是xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Inner>
</Inner>
</Root>

这里有什么想法吗?任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:3)

在过去的两年里,我已经完善了@Severin为我的项目提出的解决方案。因此,我给出了如下额外答案:

当通过XMLResource加载资源时,会调用几个辅助类来解析XML并将其映射到EMF / Ecore。可以通过更改加载选项来替换大多数类。有几个地方可以做到这一点:

  • ResourceSet有默认加载选项
  • Resource默认加载选项(通常通过生成的ResourceFactory设置)
  • Resource.load()方法可以提供加载选项

根据您拥有的访问权限(您自己生成的代码与第三方生成的代码)以及加载资源的位置/频率,您需要使用其中一种替代方法添加到加载选项中。

加载选项作为键值映射。例如,密钥由ResourceXMLResource中的常量定义。

最初描述的问题对两个键特别感兴趣:

  • XMLResource.OPTION_MISSING_PACKAGE_HANDLER提供了一个处理程序,如果EMF找不到合适的EPackage,则会调用该处理程序
  • XMLResource.OPTION_EXTENDED_META_DATA产生一个布尔值(表示是否使用扩展元数据,通常是true),或者是ExtendedMetaData的具体实例,它提供XML之间的各种映射信息和Ecore。

对于简单的情况,何时

  • 只有一个命名空间和一个EPackage涉及
  • 资源的内容类型是明确的(即,您/知道/该资源包含与您的EPackage匹配的内容)

您可以像这样执行MissingPackageHandler实施:

MissingPackageHandler mph = new MissingPackageHandler() {
  @Override
  public EPackage getPackage(final String nsURI) {
    return MyModelEPackage.eINSTANCE;
  }
};

至少在我的项目中,我还需要设置ExtendedMetaData

BasicExtendedMetaData bemd = new BasicExtendedMetaData(new EPackageRegistryImpl(EPackage.Registry.INSTANCE)) {
  @Override
  protected boolean isFeatureNamespaceMatchingLax() {
    return true;
  }
};

如果涉及多个EPackage和名称空间,则MissingPackageHandler可能过于高级,需要通过ExtendedMetaData实现直接进行区分。

根据@Severin的回答,可以这样做:

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;
  }
});

答案 1 :(得分:0)

我在ATL透视图上遇到同样的问题,我做了什么来避免“PackageNotFoundException”的问题:拳头你不应该让你的模型名称空间为NULL,识别URI的名称空间“nsURI “将有助于识别代码生成器中的Ecore模型”xml文件。所以只需命名nsURI,任何名称都匹配你的 EPackage 。另外我重写xsi:schemeLocation =“....”manulay,也许这没有意义,但最后它解决了问题