Как получить доступ к документам OWL, используя XPath в Java?

У меня есть документ OWL в форме файла XML. Я хочу извлечь элементы из этого документа. Мой код работает для простых XML-документов, но не работает с OWL XML-документами.

Я действительно хотел получить этот элемент: /rdf:RDF/owl:Ontology/rdfs:label, для которого я сделал это:

 DocumentBuilder builder = builderfactory.newDocumentBuilder();
    Document xmlDocument = builder.parse(
            new File(XpathMain.class.getResource("person.xml").getFile()));

    XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance();
    XPath xPath = factory.newXPath();
    XPathExpression xPathExpression = xPath.compile("/rdf:RDF/owl:Ontology/rdfs:label/text()");
    String nameOfTheBook = xPathExpression.evaluate(xmlDocument,XPathConstants.STRING).toString();

Я также пытался извлечь только rdfs:label элемент таким образом:

 XPathExpression xPathExpression = xPath.compile("//rdfs:label");        
 NodeList nodes = (NodeList) xPathExpression.evaluate(xmlDocument, XPathConstants.NODESET);

Но этот список узлов пуст.

Пожалуйста, дайте мне знать, где я иду не так. Я использую Java XPath API.

3 ответа

Решение

Поскольку xpath не знает используемых вами пространств имен. попробуйте использовать:

"/*[local-name()='RDF']/*[local-name()='Ontology']/*[local-name()='label']/text()"

локальное имя будет игнорировать пространства имен и будет работать (для первого найденного экземпляра)

Не запрашивайте RDF (или OWL) с XPath

Уже есть принятый ответ, но я хотел бы подробно остановиться на комментарии @ Майкла к этому вопросу. Это очень плохая идея - работать с RDF как XML (и, следовательно, с сериализацией RDF онтологии OWL), и причина этого очень проста: один и тот же граф RDF может быть сериализован в виде множества различных документов XML. В вопросе все, что просят, это rdfs:label из owl:Ontology элемент, так сколько может пойти не так? Ну, вот две сериализации онтологии.

Первый из них читается человеком и сгенерирован OWL API, когда я сохранил онтологию с помощью редактора онтологий Protégé. Я думаю, что запрос в принятом ответе сработает.

<rdf:RDF xmlns="http://www.example.com/labelledOnt#"
     xml:base="http://www.example.com/labelledOnt"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <owl:Ontology rdf:about="http://www.example.com/labelledOnt">
        <rdfs:label>Here is a label on the Ontology.</rdfs:label>
    </owl:Ontology>
</rdf:RDF>

Вот тот же график RDF, использующий меньшее количество необычных функций, доступных в кодировке RDF/XML. Это тот же граф RDF и, следовательно, та же онтология OWL. Тем не менее, нет owl:Ontology Элемент XML здесь, и запрос XPath не будет выполнен.

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns="http://www.example.com/labelledOnt#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" > 
  <rdf:Description rdf:about="http://www.example.com/labelledOnt">
    <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Ontology"/>
    <rdfs:label>Here is a label on the Ontology.</rdfs:label>
  </rdf:Description>
</rdf:RDF>

Вы не можете надежно запрашивать граф RDF в сериализации RDF/XML, используя типичные методы обработки XML.

Запрос RDF с помощью SPARQL

Что ж, если мы не можем надежно запрашивать RDF с помощью XPath, что мы должны использовать? Стандартный язык запросов для RDF - SPARQL. RDF является представлением на основе графа, а запросы SPARQL включают шаблоны графа, которые могут соответствовать графу.

В этом случае шаблон, который мы хотим сопоставить на графике, состоит из двух троек. Тройка представляет собой 3-кортеж вида [subject,predicate,object], Обе тройки имеют одну и ту же тему.

  • Первая тройка говорит, что предмет имеет тип owl:Ontology, Отношение "имеет тип" rdf:typeИтак, первая тройка [?something,rdf:type,owl:Ontology],
  • Вторая тройка говорит, что субъект (в настоящее время онтология) имеет rdfs:labelи это значение, которое нас интересует. Соответствующая тройка [?something,rdfs:label,?label],

В SPARQL после определения необходимых префиксов мы можем написать следующий запрос.

PREFIX owl: <http://www.w3.org/2002/07/owl#>                                                                                                                                                   
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>                                                                                                                                           

SELECT ?label WHERE {                                                                                                                                                                          
  ?ontology a owl:Ontology ;                                                                                                                                                                   
            rdfs:label ?label .                                                                                                                                                                
}

(Обратите внимание, что, потому что rdf:type это так часто, SPARQL включает в себя a как сокращение для этого. Запись s p1 o1; p2 o2 . это просто сокращение для двух-тройного паттерна s p1 o1 . s p2 o2 ..)

Вы можете запускать SPARQL-запросы к своей модели в Jena либо программно, либо с помощью инструментов командной строки. Если вы делаете это программно, то довольно легко получить результаты. Чтобы подтвердить, что этот запрос получает интересующее нас значение, мы можем использовать командную строку Jena для arq чтобы проверить это.

$ arq  --data labelledOnt.owl --query getLabel.sparql
--------------------------------------
| label                              |
======================================
| "Here is a label on the Ontology." |
--------------------------------------

Вы сможете использовать пространства имен в запросе, если вы реализуете javax.xml.namespace.NamespaceContext для себя. Пожалуйста, посмотрите на этот ответ /questions/15486463/xpath-prostranstva-imen-xml-i-java/15486481#15486481, здесь объясняется, как это сделать.

Другие вопросы по тегам