【问题标题】:How to compare simple and typed literals in dotnetrdf?如何比较 dotnetrdf 中的简单文字和类型文字?
【发布时间】:2016-10-13 17:51:43
【问题描述】:

我正在比较两个图表,一个来自带有简单文字对象的 Turtle 文件,另一个来自具有显式数据类型 IRI 的文件。否则图表相等。

图 A:

<s> <p> "o"

图 B:

<s> <p> "o"^^xsd:string

根据RDF 1.1 (3.3 Literals),“[s] 简单文字是数据类型为 IRI http://www.w3.org/2001/XMLSchema#string 的抽象语法文字的语法糖”。这也反映在具体的语法规范中(N-TriplesTurtleRDF XML)。

所以我希望我的两个图表都包含一个带有 URI 节点 s 主题、URI 节点 p 谓词和文字节点 o 类型为 xsd:string 对象。基于此,我希望两者之间没有区别。

但实际情况并非如此:

var graphStringA = "<http://example.com/subject> <http://example.com/predicate> \"object\".";
var graphStringB = "<http://example.com/subject> <http://example.com/predicate> \"object\"^^<http://www.w3.org/2001/XMLSchema#string>.";

var graphA = new Graph();
var graphB = new Graph();

StringParser.Parse(graphA, graphStringA);
StringParser.Parse(graphB, graphStringB);

var diff = graphA.Difference(graphB);

差异报告中添加了一个三元组,删除了一个三元组。图表不同,因为对象节点的数据类型不同:graphA.Triples.First().Object.Datatype 什么都不是,而graphB.Triples.First().Object.Datatype 是正确的 URI。


在我看来,要修改这种行为,我必须要么

  • 一直到LiteralNode(并改变它对文字节点的假设),或者
  • 创建一个新的GraphDiff(考虑到字符串文字的默认数据类型)。

一种解决方法是删除“默认”数据类型:

private static void RemoveDefaultDatatype(IGraph g)
{
    var triplesWithDefaultDatatype =
        from triple in g.Triples
        where triple.Object is ILiteralNode
        let literal = triple.Object as ILiteralNode
        where literal.DataType != null
        where literal.DataType.AbsoluteUri == "http://www.w3.org/2001/XMLSchema#string" || literal.DataType.AbsoluteUri == "http://www.w3.org/2001/XMLSchema#langString"
        select triple;

    var triplesWithNoDatatype =
        from triple in triplesWithDefaultDatatype
        let literal = triple.Object as ILiteralNode
        select new Triple(
            triple.Subject,
            triple.Predicate,
            g.CreateLiteralNode(
                literal.Value,
                literal.Language));

    g.Assert(triplesWithNoDatatype.ToArray());
    g.Retract(triplesWithDefaultDatatype);
}

在 dotnetrdf 中是否有一种方法可以以与 RDF 1.1 一致的方式将简单文字与类型化文字进行比较,而无需采用上述主要重写或解决方法?

【问题讨论】:

    标签: c# .net rdf dotnetrdf


    【解决方案1】:

    dotNetRDF 不符合 RDF 1.1,我们也不声称符合。有一个分支被重写以符合要求,但它还没有准备好远程生产。

    假设您控制解析过程,您可以使用RDF Handlers API 自定义对传入数据的处理。然后,您可以根据需要通过覆盖 HandleTriple(Triple t) 方法来去除隐含的 xsd:string 类型文字,因为它们进入系统。

    【讨论】:

      【解决方案2】:

      按照 RobV 的回答使用 Handlers API:

      class StripStringHandler : BaseRdfHandler, IWrappingRdfHandler
      {
          protected override bool HandleTripleInternal(Triple t)
          {
              if (t.Object is ILiteralNode)
              {
                  var literal = t.Object as ILiteralNode;
      
                  if (literal.DataType != null && (literal.DataType.AbsoluteUri == "http://www.w3.org/2001/XMLSchema#string" || literal.DataType.AbsoluteUri == "http://www.w3.org/2001/XMLSchema#langString"))
                  {
                      var simpleLiteral = this.CreateLiteralNode(literal.Value, literal.Language);
      
                      t = new Triple(t.Subject, t.Predicate, simpleLiteral);
                  }
              }
      
              return this.handler.HandleTriple(t);
          }
      
          private IRdfHandler handler;
      
          public StripStringHandler(IRdfHandler handler) : base(handler)
          {
              this.handler = handler;
          }
      
          public IEnumerable<IRdfHandler> InnerHandlers
          {
              get
              {
                  return this.handler.AsEnumerable();
              }
          }
      
          protected override void StartRdfInternal()
          {
              this.handler.StartRdf();
          }
      
          protected override void EndRdfInternal(bool ok)
          {
              this.handler.EndRdf(ok);
          }
      
          protected override bool HandleBaseUriInternal(Uri baseUri)
          {
              return this.handler.HandleBaseUri(baseUri);
          }
      
          protected override bool HandleNamespaceInternal(string prefix, Uri namespaceUri)
          {
              return this.handler.HandleNamespace(prefix, namespaceUri);
          }
      
          public override bool AcceptsAll
          {
              get
              {
                  return this.handler.AcceptsAll;
              }
          }
      }
      

      用法:

      class Program
      {
          static void Main()
          {
              var graphA = Load("<http://example.com/subject> <http://example.com/predicate> \"object\".");
              var graphB = Load("<http://example.com/subject> <http://example.com/predicate> \"object\"^^<http://www.w3.org/2001/XMLSchema#string>.");
      
              var diff = graphA.Difference(graphB);
      
              Debug.Assert(diff.AreEqual);
          }
      
          private static IGraph Load(string source)
          {
              var result = new Graph();
              var graphHandler = new GraphHandler(result);
              var strippingHandler = new StripStringHandler(graphHandler);
              var parser = new TurtleParser();
      
              using (var reader = new StringReader(source))
              {
                  parser.Load(strippingHandler, reader);
              }
      
              return result;
          }
      }
      

      【讨论】:

      猜你喜欢
      • 2011-08-31
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 1970-01-01
      相关资源
      最近更新 更多