如何从XSD模式编程生成EMF模型(.ecore、.genmodel)?

3
我一直在尝试作为独立应用程序的最后阶段完成此操作,将建模程序使用的文件格式转换为EMF模型。我能够将原始格式转换为XSD,然后使用Eclipse导入器手动将其转换为EMF模型,但我不知道如何以编程方式自动化此过程。Java命令可以正常工作,任何可执行相同操作的命令行语句也可以,因为我可以从Java中执行该语句。我花了一段时间寻找如何做到这一点,尝试了http://wiki.eclipse.org/Generating_Dynamic_Ecore_from_XML_Schema和其他各种潜在解决方案,但似乎都没有起作用。如果有人能够提供一些示例代码,演示如何从XSD文件生成.ecore和(/或?) .genmodel文件,我会非常感激,但即使是关于如何继续的指导也会非常有帮助。
谢谢。
2个回答

5
看一下类org.eclipse.xsd.ecore.XSDEcoreBuilder以及它在Eclipse导入向导中的使用方式。
看起来非常简单,只需调用其generate方法之一,就可以返回一个Collection<Resource>Collection<EObject>
(编辑:回答评论中的其他问题)
EPackage类是Ecore版本的xs:schema,其中包含了EClass,这些又是xs:complexType的Ecore版本。
以下代码段应该会创建并保存一个foo.ecore文件到与源XSD相同的文件夹中。如果foo.xsd有其他已导入的XSDs,则它们将转换为单独的.ecore文件,因此返回类型为Collection<Resource>
URI schemaURI = URI.createFileURI("foo.xsd");
Collection<Resource> ecoreResources = XSDEcoreBuilder.generateResources(schemaURI);
for (Resource ecoreResource : ecoreResources) {
    ecoreResource.save(null);
}

查看Eclipse源代码通常是找到像这样的问题答案的最佳方法。在维基或Eclipse新闻组中找到的内容通常已经过时了。 - Stephen C
我尝试查看Eclipse XSD导入器,以了解它如何使用XSDEcoreBuilder。它似乎做了类似的事情,生成了一个EPackage列表。http://wiki.eclipse.org/Generating_Dynamic_Ecore_from_XML_Schema中的集合也是一个EPackage列表,我认为这是因为代码后面迭代集合以获取每个单独的EPackage。然而,我不明白,您如何将此EPackage转换成例如.ecore或.genmodel格式之一,或者根本如何读取它。也就是说,我该如何处理这个EPackage?对于我的无知表示抱歉。 - ddatta
尝试调用generateResources会导致运行时错误:Exception in thread "main" java.lang.NullPointerException at org.eclipse.xsd.ecore.XSDEcoreBuilder.generateResources(XSDEcoreBuild er.java:2765) at org.eclipse.xsd.ecore.XSDEcoreBuilder.generateResources(XSDEcoreBuild er.java:2742) at ...调用generate而不是generateResources似乎可以工作;它生成了一个EPackage而不是Resource,但我不知道如何保存它。我尝试查看generateResources代码并在我的代码中模拟它,但我无法访问所有方法。谢谢您的帮助,看起来更接近了。 - ddatta
作为更新,我认为确切的问题是在generateResources中,“Resource ecoreResource = resourceSet.createResource(URI.createURI("*.ecore"));" 结束时ecoreResource仍然为空。至少,这是我从尝试通过查看Eclipse源代码在我的代码中重新创建该方法时确定的。不过,这可能只是我的代码模拟或误解的问题;我现在真的不知道。如果可以将EPackage转换为ecore,那么这可能会更容易,但我不知道是否可能。或者问题是否可以在此处确定。 - ddatta
有关这个问题的任何新信息吗?XSDEcoreBuilder似乎不再具有名为generateResources的方法。 - RoflcoptrException

2

上述代码在以下环境下运行:

版本: Luna Service Release 2 (4.4.2) 构建id: 20150219-0600

插件:

  • ATL SDK - ATLAS Transformation Language SDK 3.5.0.v201405260755 org.eclipse.m2m.atl.sdk.feature.group
  • Eclipse Modeling Project Eclipse Modeling Tools 4.4.2.20150219-0708 epp.package.modeling
  • Kermeta MDK for Ecore 1.4.0 fr.irisa.triskell.kermeta.ecore.feature.group IRISA/INRIA
  • OCL Examples and Editors SDK 3.4.4.v20150213-2254 org.eclipse.ocl.examples.feature.group
  • Eclipse Modeling Project
  • Xtext Complete SDK 2.7.3.v201411190455 org.eclipse.xtext.sdk.feature.group Eclipse Modeling Project

然而,初始的 XSD 文件会被 Ecore 内容覆盖。此外,save 操作会被调用两次(一次是 XSDResourceImpl,另一次是 EcoreResourceFactoryImpl)。我们只需要对 EcoreResourceFactoryImpl 进行操作。以下是修复后的示例代码:

    URI schemaURI = URI.createFileURI("library3.xsd");
    File outputFile = new File("library3.ecore");
    XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder(); 
    Collection<Resource> ecoreResources = xsdEcoreBuilder.generateResources(schemaURI);

    // for every resource found (includes eventually referenced XSDs)
    for (Resource ecoreResource : ecoreResources) {
        try {
            if (ecoreResource.getClass().getName().contains("EcoreResourceFactoryImpl")) {
                ecoreResource.save(new FileOutputStream(outputFile), null);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接