5

我有一个 XSD 文件,我将其转换为一个 ecore 模型,并从中生成模型代码。现在我想为该架构加载一个 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>

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

4

3 回答 3

4

在过去的两年里,我改进了@Severin 为我的项目提出的解决方案。因此,我给出一个额外的答案如下:

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

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

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

加载选项以键值映射的形式出现。Resource例如,键由和中的常量定义 XMLResource

对于最初描述的问题,有两个关键点特别重要:

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

如果涉及多个EPackages 和命名空间,则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;
  }
});
于 2017-08-01T15:17:30.387 回答
2

当您生成模型时,您可能会生成一个 [YourModelName]ResourceFactoryImpl 类。我的 KML 编辑器遇到了同样的问题,我就是这样解决的:

    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;
                }
        });
...
    }
    }
于 2014-03-18T21:39:14.550 回答
0
于 2017-03-01T07:56:51.273 回答