2013-07-18 44 views
0

我有一個我想分析和訪問節點的RDF/XML數據。 它看起來像這樣:使用Perl訪問RDF/XML/OWL文件節點

<!-- http://purl.obolibrary.org/obo/VO_0000185 --> 

    <owl:Class rdf:about="&obo;VO_0000185"> 
     <rdfs:label>Influenza virus gene</rdfs:label> 
     <rdfs:subClassOf rdf:resource="&obo;VO_0000156"/> 
     <obo:IAO_0000117>YH</obo:IAO_0000117> 
    </owl:Class> 



    <!-- http://purl.obolibrary.org/obo/VO_0000186 --> 

    <owl:Class rdf:about="&obo;VO_0000186"> 
     <rdfs:label>RNA vaccine</rdfs:label> 
     <owl:equivalentClass> 
      <owl:Class> 
       <owl:intersectionOf rdf:parseType="Collection"> 
        <rdf:Description rdf:about="&obo;VO_0000001"/> 
        <owl:Restriction> 
         <owl:onProperty rdf:resource="&obo;BFO_0000161"/> 
         <owl:someValuesFrom rdf:resource="&obo;VO_0000728"/> 
        </owl:Restriction> 
       </owl:intersectionOf> 
      </owl:Class> 
     </owl:equivalentClass> 
     <rdfs:subClassOf rdf:resource="&obo;VO_0000001"/> 
     <obo:IAO_0000116>Using RNA may eliminate the problem of having to tailor a vaccine for each individual patient with their specific immunity. The advantage of RNA is that it can be used for all immunity types and can be taken from a single cell. DNA vaccines need to produce RNA which then prompts the manufacture of proteins. However, RNA vaccine eliminates the step from DNA to RNA.</obo:IAO_0000116> 
     <obo:IAO_0000115>A vaccine that uses RNA(s) derived from a pathogen organism.</obo:IAO_0000115> 
     <obo:IAO_0000117>YH</obo:IAO_0000117> 
    </owl:Class> 

完整的RDF/XML文件可以發現here

我想要做的是做到以下幾點:它包含條目<rdfs:subClassOf rdf:resource="&obo;VO_0000001"/>

  • 訪問字面項由<rdfs:label>...</rdfs:label>
  • 所以在上面的定義

    1. 查找塊例如代碼將通過第二塊並輸出: 「RNA疫苗」。

      我目前堅持下面的代碼。在哪裏我不能 訪問該節點。什麼是正確的做法?歡迎使用XML :: LibXML 以外的解決方案。

      #!/usr/bin/perl -w 
      use strict; 
      use Data::Dumper; 
      use Carp; 
      use File::Basename; 
      use XML::LibXML 1.70; 
      
      my $filename = "VO.owl"; 
      # Obtained from http://svn.code.sf.net/p/vaccineontology/code/trunk/src/ontology/VO.owl 
      
      my $parser = XML::LibXML->new(); 
      my $doc = $parser->parse_file($filename); 
      
      foreach my $chunk ($doc->findnodes('/owl:Class')) { 
           my ($label) = $chunk->findnodes('./rdfs:label'); 
           my ($subclass) = $chunk->findnodes('./rdfs:subClassOf'); 
           print $label->to_literal; 
           print $subclass->to_literal; 
      
      } 
      
    +1

    我想我不僅應該不使用XML庫的解決方案受歡迎,而且_preferred_; [不要試圖將RDF解析爲XML](http://stackoverflow.com/a/17052385/1281433)。的確,RDF可以通過XML進行序列化,但是同一個RDF圖可以用不同的方式在XML中進行序列化,而對其中一個進行工作的XML解決方案不太可能適用於另一個。 RDF是基於圖表的表示形式,應該這樣對待。 –

    回答

    3

    解析RDF就好像它是XML是愚蠢的。完全相同的數據可以以許多不同的方式出現。例如,以下所有RDF文件都攜帶相同的數據。任何符合RDF實施必須處理它們相同...

    <!-- example 1 --> 
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> 
        <rdf:Description rdf:about="#me"> 
        <rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person" /> 
        <foaf:name>Toby Inkster</foaf:name> 
        </rdf:Description> 
    </rdf:RDF> 
    
    <!-- example 2 --> 
    <rdf:RDF 
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
        xmlns:foaf="http://xmlns.com/foaf/0.1/"> 
        <foaf:Person rdf:about="#me"> 
        <foaf:name>Toby Inkster</foaf:name> 
        </foaf:Person> 
    </rdf:RDF> 
    
    <!-- example 3 --> 
    <rdf:RDF 
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
        xmlns:foaf="http://xmlns.com/foaf/0.1/"> 
        <foaf:Person rdf:about="#me" foaf:name="Toby Inkster" /> 
    </rdf:RDF> 
    
    <!-- example 4 --> 
    <rdf:RDF 
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
        xmlns:foaf=""> 
        <rdf:Description rdf:about="#me" 
        rdf:type="http://xmlns.com/foaf/0.1/Person" 
        foaf:name="Toby Inkster" /> 
    </rdf:RDF> 
    
    <!-- example 5 --> 
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> 
        <rdf:Description rdf:ID="me"> 
        <rdf:type> 
         <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person" /> 
        </rdf:type> 
        <foaf:name>Toby Inkster</foaf:name> 
        </rdf:Description> 
    </rdf:RDF> 
    
    <!-- example 6 --> 
    <foaf:Person 
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
        xmlns:foaf="http://xmlns.com/foaf/0.1/" 
        rdf:about="#me" 
        foaf:name="Toby Inkster" /> 
    

    我可以很容易地列出半打其他的變化也一樣,但我會停在那裏。而這個RDF文件只包含兩條​​語句 - 我是一個人;我的名字是「Toby Inkster」 - OP的數據包含超過50,000條語句。

    這只是RDF的XML序列化;還有其他序列化。

    如果您嘗試使用XPath處理所有這些事情,那麼您很可能最終成爲一個鎖在某處的塔樓中的瘋子,在睡夢中嘀咕着三重奏;三倍...

    幸運的是,格雷格威廉姆斯爲你服用了這種心理健康子彈。 RDF::TrineRDF::Query不僅是Perl的最佳RDF框架;他們是任何編程語言中最好的。

    這裏是如何的OP的任務可以使用RDF ::特里尼和RDF ::查詢來實現:

    #!/usr/bin/env perl 
    
    use v5.12; 
    use RDF::Trine; 
    use RDF::Query; 
    
    my $model = 'RDF::Trine::Model'->new(
        'RDF::Trine::Store::DBI'->new(
         'vo', 
         'dbi:SQLite:dbname=/tmp/vo.sqlite', 
         '', # no username 
         '', # no password 
        ), 
    ); 
    
    'RDF::Trine::Parser::RDFXML'->new->parse_url_into_model(
        'http://svn.code.sf.net/p/vaccineontology/code/trunk/src/ontology/VO.owl', 
        $model, 
    ) unless $model->size > 0; 
    
    my $query = RDF::Query->new(<<'SPARQL'); 
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
    SELECT ?super_label ?sub_label 
    WHERE { 
        ?sub rdfs:subClassOf ?super . 
        ?sub rdfs:label ?sub_label . 
        ?super rdfs:label ?super_label . 
    } 
    LIMIT 5 
    SPARQL 
    
    print $query->execute($model)->as_string; 
    

    輸出示例:

    +----------------------------+----------------------------------+ 
    | super_label    | sub_label      | 
    +----------------------------+----------------------------------+ 
    | "Aves vaccine"    | "Ducks vaccine"     | 
    | "route of administration" | "intravaginal route"    | 
    | "Shigella gene"   | "aroA from Shigella"    | 
    | "Papillomavirus vaccine" | "Bovine papillomavirus vaccine" | 
    | "virus protein"   | "Feline leukemia virus protein" | 
    +----------------------------+----------------------------------+ 
    

    UPDATE:這裏有一個SPARQL查詢可以插入上面的腳本來檢索您想要的數據:

    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
    PREFIX obo: <http://purl.obolibrary.org/obo/> 
    SELECT ?subclass ?label 
    WHERE { 
        ?subclass 
         rdfs:subClassOf obo:VO_0000001 ; 
         rdfs:label ?label . 
    } 
    
    +0

    感謝您的解釋。我通常嘗試遠離XML,並且有一些我特別試圖避免的XML技術(例如XSD,SOAP)--- RDF將被添加到此列表中:-) –

    +1

    您當然不應該將RDF添加到列表中您希望避免的XML技術。如果你喜歡,避免它;精細。但是(儘管有一個XML序列化),它不是一種XML技術,所以你會把它放在錯誤的列表中。 – tobyink

    +0

    @tobyink:謝謝。但我怎樣才能確保標籤輸出是VO_0000001的子類。 – neversaint

    2

    /owl:Class不是XML文檔中的根元素。您必須將根元素包含到XPath中:/rdf:RDF/owl:Class。或者,如果要獲取所有出現的內容,則無論XML樹中的深度如何,都可以使用雙斜線表示法://owl:Class

    +0

    謝謝Slaven。但我無法訪問'subClassOf'內容。什麼是正確的命令? – neversaint

    +1

    您可以訪問subClassOf。但它沒有字面值(這是標籤之間的文本內容,所以它顯示爲空字符串,而不是'to_literal()'嘗試'serialize'來查看它匹配的內容。 –

    +0

    @neversaint你的意思是什麼子類內容?問題你說你試圖訪問類的'rdfs:label'屬性的值,然後確定這些類的'owl:subClassOf'屬性的值。你試圖從子類中獲得什麼內容? –

    3

    查看perlrdf.org網站,其中包含指向許多用於使用RDF的Perl包的鏈接。

    由於RDF/XML不是標準化的序列化,即使用不同的XML格式表示相同的數據,具體取決於用於序列化的工具,使用這些可能會更靈活,更容易使用XPath訪問RDF/XML它。