如何更新 OWL ontology 文件以添加具有某些属性的新个体?
How to update an OWL ontology file in order to add a new individual with some properties?
我有一个 ontology 在 protege 4.3.0 中创建并存储在 OWL 文件中。我需要向此 ontology 添加一些人并更新此文件。由于这些人彼此非常相似,我想利用 OWL API 比手动使用程序更快地添加它们。
我的目标如下:
- 添加新个人
#individualSimpleSubType
- 为这个人添加类型
#SimpleSubType
(#SimpleSubType
是#SimpleType
的子class)
- 向此人添加以下对象 属性 断言:
#hasProperty1
关联到 #PropertyValue1
- 向此人添加以下对象 属性 断言:
#hasProperty2
关联到 #PropertyValue2
ontology 中已存在以下信息:
- class
#SimpleType
及其子class#SimpleSubType
- 对象属性
#hasProperty1
和 #hasProperty2
- 个体
#PropertyValue1
和#PropertyValue2
以下是我用来实现该目标的代码:
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
try {
OWLOntology ontology = manager.loadOntologyFromOntologyDocument(new File("ontology.owl"));
IRI ontologyIRI = ontology.getOntologyID().getOntologyIRI();
PrefixManager prefixManager = new DefaultPrefixManager(ontologyIRI.toString().concat("#"));
OWLDataFactory dataFactory = manager.getOWLDataFactory();
OWLReasonerFactory reasonerFactory = new StructuralReasonerFactory();
OWLReasoner reasoner = reasonerFactory.createReasoner(ontology);
reasoner.precomputeInferences();
// Get all subclasses of SimpleType stored within the loaded ontology.
OWLClassNodeSet clsSimpleSubTypes = new OWLClassNodeSet();
OWLClass simpleTypeClass = dataFactory.getOWLClass(":SimpleType", prefixManager);
clsSimpleSubTypes.addDifferentEntities(reasoner.getSubClasses(simpleTypeClass, true).getFlattened());
// Get two object properties stored within the loaded ontology.
OWLObjectPropertyExpression objProperty1 = dataFactory.getOWLObjectProperty(IRI.create(ontologyIRI + "#hasProperty1"));
OWLObjectPropertyExpression objProperty2 = dataFactory.getOWLObjectProperty(IRI.create(ontologyIRI + "#hasProperty2"));
// Get two property values stored within the loaded ontology.
OWLNamedIndividual propertyValue1 = dataFactory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#PropertyValue1"));
OWLNamedIndividual propertyValue2 = dataFactory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#PropertyValue2"));
for (OWLClass cls : clsSimpleSubTypes.getFlattened())
{
if (cls.getIRI().toString().endsWith("#SimpleSubType")) {
// Create the new individual
OWLNamedIndividual po = factory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#individualSimpleSubType"));
// individualSimpleSubType is of type SimpleSubType
OWLClassAssertionAxiom assertion = dataFactory.getOWLClassAssertionAxiom(cls, po);
manager.addAxiom(ontology, assertion);
// individualSimpleSubType has object property PropertyValue1
OWLObjectPropertyAssertionAxiom objProperty1Axiom = dataFactory.getOWLObjectPropertyAssertionAxiom(objProperty1, po, propertyValue1);
manager.addAxiom(ontology, objProperty1Axiom);
// individualSimpleSubType has object property PropertyValue2
OWLObjectPropertyAssertionAxiom objProperty2Axiom = dataFactory.getOWLObjectPropertyAssertionAxiom(objProperty2, po, propertyValue2);
manager.addAxiom(ontology, objProperty2Axiom);
break;
}
}
//File destinationFile = new File("ontology-new-data.owl");
//OWLOntologyFormat format = manager.getOntologyFormat(ontology);
//manager.saveOntology(ontology, format, IRI.create(destinationFile.toURI()));
manager.saveOntology(ontology);
} catch (OWLOntologyCreationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OWLOntologyStorageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是,使用上面的代码,我得到的结果与使用 Protegé 得到的结果不同。
如果我使用 Protegé 如上所述添加新个人,OWL 文件会更新并添加以下 XML 行:
<!-- http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#individualSimpleSubType -->
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#individualSimpleSubType">
<rdf:type rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#SimpleSubType"/>
<hasProperty1 rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#PropertyValue1"/>
<hasProperty2 rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#PropertyValue2"/>
</owl:NamedIndividual>
但是,如果我使用上面的Java代码,保存ontology还涉及其他行的修改:将与上面相同的XML行添加到文件中,但是其他行也修改如下。
下面几行写在上面Java代码保存的OWL文件的开头(但是我用Protégé保存ontology后没有写这些行执行相同的修改)。
<!DOCTYPE rdf:RDF [
<!ENTITY terms "http://purl.org/dc/terms/" >
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY skos "http://www.w3.org/2004/02/skos/core#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
然后,在一些标签的属性中加入一定的前缀,所以:
- 原OWL文件的属性
rdf:resource="&rdf;List"
被替换为rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"
- 原OWL文件的属性
rdf:resource="&owl;TransitiveProperty"
被替换为rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"
- 原OWL文件的属性
rdf:about="&terms;description"
被替换为rdf:about="http://purl.org/dc/terms/description"
- 原OWL文件的属性
rdf:resource="&rdfs;Literal"
被替换为rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"
- 原OWL文件的属性
rdf:resource="&xsd;hexBinary"
被替换为rdf:resource="http://www.w3.org/2001/XMLSchema#hexBinary"
- 原OWL文件的属性
rdf:resource="&xsd;string"
被替换为rdf:resource="http://www.w3.org/2001/XMLSchema#string"
- 原OWL文件的属性
rdf:resource="&skos;Concept"
被替换为rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"
- 原OWL文件的属性
rdf:resource="&skos;ConceptScheme"
被替换为rdf:resource="http://www.w3.org/2004/02/skos/core#ConceptScheme"
这种奇怪行为的原因是什么?
在我的 Eclipse 项目中,我导入了与 OWL API 3.4.2 相关的 jar 文件,该版本与 Protegé 4.3.0 中集成的版本相同。
问题是从文件中读取时,原始 ontology 中的前缀没有被保留。这已在 OWL API 的更新版本中得到修复。 3.5.2 和 4.0.2(4.1.0 尚未发布)应该允许您找到 ontology 格式对象中设置的前缀。
为了保证这些前缀也用于实体(例如 &rdf;
之类的东西),您应该调用
XMLWriterPreferences.getInstance().setUseNamespaceEntities(true);
在保存 ontology 之前。
请注意,这些不是语义差异 - 它们只是 XML 级别的句法差异。无论前缀是否缩短为实体,本体在语义上都是等价的。
我有一个 ontology 在 protege 4.3.0 中创建并存储在 OWL 文件中。我需要向此 ontology 添加一些人并更新此文件。由于这些人彼此非常相似,我想利用 OWL API 比手动使用程序更快地添加它们。
我的目标如下:
- 添加新个人
#individualSimpleSubType
- 为这个人添加类型
#SimpleSubType
(#SimpleSubType
是#SimpleType
的子class) - 向此人添加以下对象 属性 断言:
#hasProperty1
关联到#PropertyValue1
- 向此人添加以下对象 属性 断言:
#hasProperty2
关联到#PropertyValue2
ontology 中已存在以下信息:
- class
#SimpleType
及其子class#SimpleSubType
- 对象属性
#hasProperty1
和#hasProperty2
- 个体
#PropertyValue1
和#PropertyValue2
以下是我用来实现该目标的代码:
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
try {
OWLOntology ontology = manager.loadOntologyFromOntologyDocument(new File("ontology.owl"));
IRI ontologyIRI = ontology.getOntologyID().getOntologyIRI();
PrefixManager prefixManager = new DefaultPrefixManager(ontologyIRI.toString().concat("#"));
OWLDataFactory dataFactory = manager.getOWLDataFactory();
OWLReasonerFactory reasonerFactory = new StructuralReasonerFactory();
OWLReasoner reasoner = reasonerFactory.createReasoner(ontology);
reasoner.precomputeInferences();
// Get all subclasses of SimpleType stored within the loaded ontology.
OWLClassNodeSet clsSimpleSubTypes = new OWLClassNodeSet();
OWLClass simpleTypeClass = dataFactory.getOWLClass(":SimpleType", prefixManager);
clsSimpleSubTypes.addDifferentEntities(reasoner.getSubClasses(simpleTypeClass, true).getFlattened());
// Get two object properties stored within the loaded ontology.
OWLObjectPropertyExpression objProperty1 = dataFactory.getOWLObjectProperty(IRI.create(ontologyIRI + "#hasProperty1"));
OWLObjectPropertyExpression objProperty2 = dataFactory.getOWLObjectProperty(IRI.create(ontologyIRI + "#hasProperty2"));
// Get two property values stored within the loaded ontology.
OWLNamedIndividual propertyValue1 = dataFactory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#PropertyValue1"));
OWLNamedIndividual propertyValue2 = dataFactory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#PropertyValue2"));
for (OWLClass cls : clsSimpleSubTypes.getFlattened())
{
if (cls.getIRI().toString().endsWith("#SimpleSubType")) {
// Create the new individual
OWLNamedIndividual po = factory.getOWLNamedIndividual(IRI.create(ontologyIRI + "#individualSimpleSubType"));
// individualSimpleSubType is of type SimpleSubType
OWLClassAssertionAxiom assertion = dataFactory.getOWLClassAssertionAxiom(cls, po);
manager.addAxiom(ontology, assertion);
// individualSimpleSubType has object property PropertyValue1
OWLObjectPropertyAssertionAxiom objProperty1Axiom = dataFactory.getOWLObjectPropertyAssertionAxiom(objProperty1, po, propertyValue1);
manager.addAxiom(ontology, objProperty1Axiom);
// individualSimpleSubType has object property PropertyValue2
OWLObjectPropertyAssertionAxiom objProperty2Axiom = dataFactory.getOWLObjectPropertyAssertionAxiom(objProperty2, po, propertyValue2);
manager.addAxiom(ontology, objProperty2Axiom);
break;
}
}
//File destinationFile = new File("ontology-new-data.owl");
//OWLOntologyFormat format = manager.getOntologyFormat(ontology);
//manager.saveOntology(ontology, format, IRI.create(destinationFile.toURI()));
manager.saveOntology(ontology);
} catch (OWLOntologyCreationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OWLOntologyStorageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是,使用上面的代码,我得到的结果与使用 Protegé 得到的结果不同。
如果我使用 Protegé 如上所述添加新个人,OWL 文件会更新并添加以下 XML 行:
<!-- http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#individualSimpleSubType -->
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#individualSimpleSubType">
<rdf:type rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#SimpleSubType"/>
<hasProperty1 rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#PropertyValue1"/>
<hasProperty2 rdf:resource="http://www.semanticweb.org/vincenzo/ontologies/2015/7/ontology.owl#PropertyValue2"/>
</owl:NamedIndividual>
但是,如果我使用上面的Java代码,保存ontology还涉及其他行的修改:将与上面相同的XML行添加到文件中,但是其他行也修改如下。
下面几行写在上面Java代码保存的OWL文件的开头(但是我用Protégé保存ontology后没有写这些行执行相同的修改)。
<!DOCTYPE rdf:RDF [
<!ENTITY terms "http://purl.org/dc/terms/" >
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY skos "http://www.w3.org/2004/02/skos/core#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
然后,在一些标签的属性中加入一定的前缀,所以:
- 原OWL文件的属性
rdf:resource="&rdf;List"
被替换为rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"
- 原OWL文件的属性
rdf:resource="&owl;TransitiveProperty"
被替换为rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"
- 原OWL文件的属性
rdf:about="&terms;description"
被替换为rdf:about="http://purl.org/dc/terms/description"
- 原OWL文件的属性
rdf:resource="&rdfs;Literal"
被替换为rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"
- 原OWL文件的属性
rdf:resource="&xsd;hexBinary"
被替换为rdf:resource="http://www.w3.org/2001/XMLSchema#hexBinary"
- 原OWL文件的属性
rdf:resource="&xsd;string"
被替换为rdf:resource="http://www.w3.org/2001/XMLSchema#string"
- 原OWL文件的属性
rdf:resource="&skos;Concept"
被替换为rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"
- 原OWL文件的属性
rdf:resource="&skos;ConceptScheme"
被替换为rdf:resource="http://www.w3.org/2004/02/skos/core#ConceptScheme"
这种奇怪行为的原因是什么?
在我的 Eclipse 项目中,我导入了与 OWL API 3.4.2 相关的 jar 文件,该版本与 Protegé 4.3.0 中集成的版本相同。
问题是从文件中读取时,原始 ontology 中的前缀没有被保留。这已在 OWL API 的更新版本中得到修复。 3.5.2 和 4.0.2(4.1.0 尚未发布)应该允许您找到 ontology 格式对象中设置的前缀。
为了保证这些前缀也用于实体(例如 &rdf;
之类的东西),您应该调用
XMLWriterPreferences.getInstance().setUseNamespaceEntities(true);
在保存 ontology 之前。
请注意,这些不是语义差异 - 它们只是 XML 级别的句法差异。无论前缀是否缩短为实体,本体在语义上都是等价的。