如何匹配CIM / RDF中的JAXB元素?

时间:2014-03-15 20:40:27

标签: java xml jaxb rdf

尝试根据IEC 61970(通用信息模型,电力系统模型)从CIM / XML文件加载模型,我发现了一个问题; 根据JAXB,元素之间的图形由@XmlREF @XmlID提供,这两者应该等于匹配。但是在CIM / RDF中,通过ID引用资源,即rdf:resource =“#_ 37C0E103000D40CD812C47572C31C0AD”包含“#”字符,因此在rdf中JAXB无法匹配“GeographicalRegion”与“SubGeographicalRegion.Region” :资源属性存在“#”字符。

这是一个例子:

<cim:GeographicalRegion rdf:ID="_37C0E103000D40CD812C47572C31C0AD">
<cim:IdentifiedObject.name>GeoRegion</cim:IdentifiedObject.name>
<cim:IdentifiedObject.localName>OpenCIM3bus</cim:IdentifiedObject.localName>
</cim:GeographicalRegion>
<cim:SubGeographicalRegion rdf:ID="_ID_SubGeographicalRegion">
<cim:IdentifiedObject.name>SubRegion</cim:IdentifiedObject.name>
<cim:IdentifiedObject.localName>SubRegion</cim:IdentifiedObject.localName>
<cim:SubGeographicalRegion.Region rdf:resource="#_37C0E103000D40CD812C47572C31C0AD"/>
</cim:SubGeographicalRegion>

1 个答案:

答案 0 :(得分:0)

我意识到您正在寻求使用JAXB的解决方案,但我建议您考虑使用基于RDF的解决方案,因为它更灵活,更强大。您基本上都在尝试重新构建已经内置的RDF解析器.RDF / XML是一种难以解析的格式,尝试破解您自己的解析并不是很有意义 - 特别是因为有文件非常不同的XML结构可以表达完全相同的信息:这只有在查看RDF级别时才会变得明显。您可能会发现您的JAXB解析器解决方法适用于一个CIM / RDF文件,但在另一个CIM / RDF文件上完全失败。

所以,这是一个如何使用Sesame RDF API处理文件的示例。不涉及推理,这只是解析文件并将其放入内存中的RDF模型,然后您可以从任何角度进行操作和查询。

假设您的CIM文件的根元素如下所示:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" 
         xmlns:cim="http://example.org/cim/">

(当然只是猜测,但我需要前缀作为正确的例子)

然后你可以使用Sesame的Rio RDF / XML解析器执行以下操作:

 String baseURI = "http://example.org/my/file";
 FileInputStream in = new FileInputStream("/path/to/my/cim.rdf"); 
 Model model = Rio.parse(in, baseURI, RDFFormat.RDFXML);

这将创建文档的内存中RDF模型。然后,您可以简单地对其进行过滤查询。例如,要打印出_37C0E103000D40CD812C47572C31C0ADSubGeographicalRegion.Region的所有资源的属性:

 String CIM_NS = "http://example.org/cim/";
 ValueFactory vf = ValueFactoryImpl.getInstance();
 URI subRegion = vf.createURI(CIM_NS, "SubGeographicalRegion.Region");
 URI res = vf.createURI("http://example.org/my/file#_37C0E103000D40CD812C47572C31C0AD");
 Set<Resource> subs = model.filter(null, subRegion, res).subjects();

 for (Resource sub: subs) {
     System.out.println("resource: " + sub + " has the following properties: ");
     for (URI prop: model.filter(sub, null, null).predicates()) {
          System.out.println(prop + ": " + model.filter(sub, prop, null).objectValue());
     }
 } 

当然,此时您还可以选择将模型转换为其他语法格式,以便您的应用程序进一步处理 - 您认为合适。关键是RDF / XML解析器已经为您解决了带有前导#和无标识符的标识符之间的差异。

这当然只是个人意见,因为我不知道您的用例的详细信息,但我认为您会发现这非常快速和灵活。我还应该指出,虽然上述解决方案将整个模型保留在内存中,但如果您发现文件太大,则可以轻松地将其调整为更流式(因此内存密集程度更低)的方法。