• RDF解析


    RDF解析

    1.1 简介

    gStore 的 RDF 解析发生在构建数据库时(包括使用 gbuild 和 ghttp 来构建数据库)。如使用 gbuild 构建库:

    $ bin/gbuild -db example -f example.nt
    
    • 1

    则 gStore 会读入 RDF 文件 example.nt ,对其进行解析,将解析得到的结果存入 example 库中。

    目前gStore支持的 RDF 数据格式为 Turtle

    1.2 类层次结构

    RDF 解析由 RDFParser 类完成。其成员变量包括一个 TurtleParser 类对象:TurtleParser 为开源系统 RDF-3X 提供的 RDF 解析模块(2008 年版本)。RDFParser 以 TurtleParser 的 RDF 解析功能为基础,在此之上补全了符合当前 RDF 标准的合法性检查,并与建库的相应接口适配。

    1.3 RDFParser::parseFile

    RDFParser::parseFile 为 RDFParser 类中最关键的成员函数,它调用 TurtleParser 解析文件中的三元组,并对成功解析的三元组按照 RDF 1.1 标准的要求进一步进行语法检查。

    函数原型:

    int parseFile(TripleWithObjType* _triple_array, int& _triple_num, string _error_log="", int init_line=0);
    
    • 1

    关键代码段说明如下。

    将解析过程中的报错输出到日志文件 _error_log (函数参数)中:

    if (!_error_log.empty())
    {
      if (_error_log == "NULL")
        cout.setstate(ios_base::badbit);	// Silent output
      else
      {
        ofile.open(_error_log,ios::app);
        if (ofile)
        {
          cout << "Error log file: " << _error_log << endl;
          cout.rdbuf(ofile.rdbuf());
        }
        else
          cout << "Error log file cannot be opened." << endl;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    由于采取批量解析的策略,每次调用此函数至多解析 RDFParser::TRIPLE_NUM_PER_GROUP 个三元组:(以下介绍的代码均在此 while 循环中)

    while (_triple_num < RDFParser::TRIPLE_NUM_PER_GROUP)
    
    • 1

    因此,上层会多次调用此函数以完成对整个 RDF 文件的解析(Database::sub2id_pre2id_obj2id_RDFintoSignature函数):

    while (true)
    {
      int parse_triple_num = 0;
    
      _parser.parseFile(triple_array, parse_triple_num);
      
      ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    调用 TurtleParser ,捕捉异常:

    try
    {
      if (!this->_TurtleParser.parse(rawSubject, rawPredicate, rawObject, _objectType, _objectSubType))		break;
    }
    catch (const TurtleParser::Exception& _e)
    {
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    当解析成功的三元组宾语为字面值、且为数值类型(带有数值类型后缀或为数值表示,如 “1”^^ 或 1)时,对它进行进一步的语法有效性检查。例如对 xsd:integer (即 )类型,需要检查是否越界:

    ...
    else if (_objectType == Type::Type_Integer)
    {
      try
      {
        stoll(rawObject);
      }
      catch (invalid_argument& e)
      {
        errorMsg = "Object integer value invalid";
        cout << "Line " << numLines << " (<" << rawSubject << "> <" << rawPredicate \
          << "> <" << rawObject << ">): " << errorMsg << endl;
        continue;
      }
      catch (out_of_range& e)
      {
        errorMsg = "Object integer out of range";
        cout << "Line " << numLines << " (<" << rawSubject << "> <" << rawPredicate \
          << "> <" << rawObject << ">): " << errorMsg << endl;
        continue;
      }
      _object = "\"" + rawObject + "\"^^";
    }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1.4 TurtleParser::parse

    TurtleParser::parse 为 TurtleParser 类中最关键的成员函数,它驱动 RDF 三元组解析的全过程。

    函数原型:

    bool parse(std::string& subject,std::string& predicate,std::string& object,Type::Type_ID& objectType,std::string& objectSubType);
    
    • 1

    关键代码段说明如下。

    根据当前已获取的三元组数量 triplesReader 判断 triples 中是否有已解析但未获取的三元组,若有,提取出其各部分赋值给输入参数,返回真:

    // Some triples left?
    if (triplesReader=triples.size()) {
         triples.clear();
         triplesReader=0;
      }
      return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    否则,判断输入流是否结束(若在遇到任何三元组前结束,则返回假),过程中若遇到 RDF 指令则调用 parseDirective 函数解析,并继续读入:

    // No, check if the input is done
    Lexer::Token token;
    while (true) {
      token=lexer.next(subject);
      if (token==Lexer::Token_Eof) return false;
    
      // A directive?
      if (token==Lexer::Token_At) {
         parseDirective();
         continue;
      } else break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    直至遇到三元组数据,将各参数传递给 parseTriple 函数解析之,返回真:

    // No, parse a triple
    parseTriple(token,subject,predicate,object,objectType,objectSubType);
    return true;
    
    • 1
    • 2
    • 3

    1.5 小结

    本章介绍了 gStore 的 RDF 解析机制,主要详细分析了两个相关类中的核心函数:RDFParser::parseFile 和 TurtleParser::parse(前者调用后者),建议在阅读的同时结合源码 Parser/RDFParser.cpp、Parser/TurtleParser.cpp 一起分析,会更容易理解。接下来我们拟将分析 gStore 的 SPARQL 解析机制。

  • 相关阅读:
    数据结构学习笔记——顺序存储结构实现串
    Win11一键重装系统后如何使用自带的故障检测修复功能
    vscode中vue项目引入的组件的颜色没区分解决办法
    Vue学习:计算属性
    <Zero to One> 1.dot-com crash that still guide business thinking today
    Liquibase-数据库脚本版本管理控制
    查询快递 批量查询物流信息并筛选出无物流信单号
    准备篇(二)Python 教程
    平曲线坐标、反算桩号计算程序
    【TCP】粘包问题 以及 异常处理
  • 原文地址:https://blog.csdn.net/weixin_48167662/article/details/126518380