如何使用EMF读取XML文件?

8

EMF代表Eclipse建模框架。

我必须在我的课程项目中使用EMF。我正在尝试理解如何使用EMF来实现以下功能:

  1. 读取XML,
  2. 将值放入对象中。
  3. 使用ORM将对象中的值持久化到数据库中 - 完成。
  4. 使用ORM从数据库获取数据并生成XML。

我需要使用以下工具完成所有这些操作:EMF(完全不知道是什么)和JPA(已完成)。

我已经使用过JAXB,我知道可以使用JAXB来完成此操作,但是(EMF == JAXB)吗?!

我已经创建了许多Java类,但它们太多了!我应该在哪里实现读/写方法,如何运行EMF项目?

谢谢。

更新1 提示 http://www.eclipsezone.com/eclipse/forums/t58829.html

更新2

我有模式并且我已经使用.xsd生成了模型代码。现在我在从XML文件中读取数据方面遇到问题。


我认为EMF并不是为那个目的而设计的。它是一个建模框架,而不是绑定框架。 - Bozho
它用于XML绑定,我对此非常确定。 - zengr
@Bozho - EMF是一个建模框架或绑定框架(也可以用作)。这取决于你从哪里开始……以及你的观点。(这是元建模的一个经常被误解的方面。模型可以被视为数据,反之亦然。) - Stephen C
5个回答

14
您可以使用EMF读取任意XML文件,前提是您拥有它们的XSD,并且甚至不必从XSD生成Java类。
我几个月前在博客中分享了这个方法,但我也将代码片段粘贴在这里。如果需要稍微详细的解释,请查看我的博客文章: 如何使用EMF加载和比较任意XML文件

首先,您需要加载XSD并初始化一些内容:

// generate EPackages from schemas
XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder();
Collection generatedPackages = xsdEcoreBuilder.generate(schemaURI);

// register the packages loaded from XSD
for (EObject generatedEObject : generatedPackages) {
    if (generatedEObject instanceof EPackage) {
        EPackage generatedPackage = (EPackage) generatedEObject;
        EPackage.Registry.INSTANCE.put(generatedPackage.getNsURI(),
            generatedPackage);
    }
}

// add file extension to registry
ResourceFactoryRegistryImpl.INSTANCE.getExtensionToFactoryMap()
    .put(MY_FILE_EXTENSION, new GenericXMLResourceFactoryImpl());

之后,您可以像往常一样加载XML文件:

ResourceSet resourceSet = ResourceSetFactory.createResourceSet();
Resource resource = resourceSet.getResource(xmlURI, true);
resource.load(Collections.EMPTY_MAP);
EObject root = resource.getContents().get(0);

嗨,@Zsolt Török - 我应该在哪个包中找到 ResourceSetFactory - Magick

5
EMF使用(默认,最流行的方式)XMIResourceImpl序列化数据模型,严格使用XMI格式,而不是自定义XML结构。
有关EMF及其用例的文章,请参见http://eclipsedriven.blogspot.com/
我同意其他答案者的看法,EMF可能不是您想要的。
如果我真的想在EMF中使用自定义XML结构(即不是XMI),我可能会使用JAXB来编组/取消编组我的EMF对象(EObjects)。
因此,EMF与JAXB不同,它们具有不同的目的和目标。实际上,您可能可以以某种方式将EMF和JAXB结合起来。我从未尝试过,但似乎有有效的用例。(如上所述,用于将EMF对象编组/取消编组为XML)
要理解EMF,您需要改变范式。首先删除“XML”部分,让它从您的头脑中消失。然后我建议您执行以下操作:
  1. 创建一个空的EMF项目。
  2. 创建一个简单的Ecore文件(.ecore),或从互联网上获取。或将任何XML Schema/UML文件导入到Ecore模型中。
  3. 右键单击EClass,然后选择“创建动态实例”,这将创建一个.xmi文件。
  4. 使用Eclipse打开.xmi文件,这将为该模型打开EMF编辑器。根据需要进行编辑。
  5. 检查(编辑后的).xmi文件的内容。您将看到格式与Ecore模型完全符合。您将无法更改/自定义模型<->XMI文件的映射,因为正如名称所示,XMIResourceImpl仅读取/保存XMI文件(这恰好是基于XML实现的),但它不会读取/保存任意XML格式。

EMF支持读取/写入XML Schema元模型(即XSD文件),以便将其转换为Ecore元模型,但不支持符合此类模式的XML文件(甚至不符合Ecore),除非这些文件采用XMI格式。

要将EMF模型持久化到关系数据库中,请参阅: http://eclipsedriven.blogspot.com/2010/12/persisting-emf-objects-to-rdbms-with.html

我正在使用Teneo。(可选CDO)

关于“XML”,如果您坚持使用XMI并对此感到满意,EMF会使您的生活变得更加轻松,因为您不需要进行任何映射(与JAXB不同)。缺点是我们的对象必须是EMF对象。

EMF对象是由EMF生成并实现EObject并直接或间接扩展EObjectImpl的对象。通常情况下,您不希望手动编写EMF对象,这将是一项繁琐的工作。另一方面,JAXB“对象”通常是纯领域对象POJO,并且没有来自JAXB的其他要求。请注意,与JAXB不同,EMF对象不是POJOs。这解释了EMF和JAXB之间另一个不同的目标。它们的重叠程度比您想象的要少。

从XMI(而不是XML)读取非常容易:

XMIResource resource = new XMIResourceImpl(URI.create("file:/path/to/mymodel.xmi"));
resource.load(null);
System.out.println( resource.eContents().get(0) );

2
我写了一个小程序,使用emftriple(前身为emf4sw)进行基本的模型格式转换,即将Ecore XMI(XML文件)转换为RDF TTL。
我在这里使用了一些答案中的技巧,所以谢谢大家!
也许源代码可以给你灵感:https://github.com/frostyandy2k/model-transformer

1

处理这种情况的常规方法是从XML模式开始,然后使用它来生成EMF模型,最后生成Java代码。在this EMF tutorial中有所描述。

您不需要实现读/写方法。相反,您可以利用EMF库中的代码来进行XML导入和导出。我现在没有我的EMF书副本在我面前,但在那里有涉及。或者,在加载或保存模型实例时,请查看生成的EMF编辑器执行的操作。

编辑

这里有一个资源实用类,来自我几年前开发的基于EMF的项目。看一下load*方法。请注意,这不一定是最好的方法...但对我有效。

编辑2

我刚意识到我使用的是XMI而不是纯XML。配置带有自定义模式和(可能)自定义模式映射的XML读取器可能会有所不同。因此,回到我的原始答案,看生成的代码!!


你能给我一个起点吗?EMF库是什么,它有读/写XML文件的方法吗? - zengr

0

EMF并不是为了读取任意的XML文件而设计的。EMF将XML作为后端使用。你的XML文件来自哪里/符合哪个模式?如果你有模式,那么你可以使用它来创建一个EMF模型,进而希望能够读取你的XML文件。

否则,你将不得不反向工程一个确实序列化到你的XML的EMF模型,以便你能够读取它,但这将是一种hack。

在UPDATE2之后

我想下一个问题是“你在加载文件时遇到了什么问题”。你是如何做的,有什么不起作用的地方吗?或者你不知道该怎么做?

首先,你必须为你的资源集(你想要处理的文件集的内存表示)配置工厂,然后使用getResource(URI, bool)加载文件。以下是我正在做的一些UML内容的示例:

resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
resourceSet.getPackageRegistry().put("http://www.eclipse.org/uml2/2.0.0/UML", UMLPackage.eINSTANCE);
Resource r = resourceSet.getResource(uriToYourFile,true);
YourModelRootType root = (YourModelRootType) r.getContents().get(0);

你已经有了教程的链接,其中应该已经涵盖了所有内容。然后,你可以使用生成的Java API从“root”开始工作。

我对ORM方面没有经验,但也许你应该看一下CDO


是的,在寻求将 EMF 模型存储在数据库中时,CDO 或 Teneo 值得研究。Teneo:http://www.eclipse.org/modeling/emft/?project=teneo - lothar

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