Skip to content

Latest commit

 

History

History
executable file
·
311 lines (255 loc) · 12.1 KB

README.md

File metadata and controls

executable file
·
311 lines (255 loc) · 12.1 KB

RDF::RDFa reader/writer

RDFa parser for RDF.rb.

DESCRIPTION

RDF::RDFa is an RDFa reader and writer for Ruby using the RDF.rb library suite.

FEATURES

RDF::RDFa parses RDFa into statements or triples.

  • Fully compliant RDFa 1.1 parser.
  • Template-based Writer to generate XHTML+RDFa.
    • Writer uses user-replacable Haml-based templates to generate RDFa.
  • Uses Nokogiri for parsing HTML/SVG
  • RDFa tests use SPARQL for most tests due to Rasqal limitations. Other tests compare directly against N-triples.

Install with 'gem install rdf-rdfa'

Usage

Reading RDF data in the RDFa format

RDF::RDFa::Reader.open("etc/foaf.html") do |reader|
  reader.each_statement do |statement|
    puts statement.inspect
  end
end

Writing RDF data using the XHTML+RDFa format

require 'rdf/rdfa'

RDF::RDFa::Writer.open("hello.html") do |writer|
  writer << RDF::Graph.new do |graph|
    graph << [:hello, RDF::DC.title, "Hello, world!"]
  end
end

Note that prefixes may be chained between Reader and Writer, so that the Writer will use the same prefix definitions found during parsing:

prefixes = {}
graph = RDF::Graph.load("etc/foaf.html", :prefixes => prefixes)
puts graph.dump(:rdfa, :prefixes => prefixes)

Template-based Writer

The RDFa writer uses Haml templates for code generation. This allows fully customizable RDFa output in a variety of host languages. The default template generates human readable HTML5 output. A minimal template generates HTML, which is not intended for human consumption.

To specify an alternative Haml template, consider the following:

require 'rdf/rdfa'

RDF::RDFa::Writer.buffer(:haml => RDF::RDFa::Writer::MIN_HAML) << graph

The template hash defines four Haml templates:

  • doc: Document Template, takes an ordered list of _subject_s and yields each one to be rendered. Described further in {RDF::RDFa::Writer#render_document}.

    !!! XML
    !!! 5
    %html{:xmlns => "http://www.w3.org/1999/xhtml", :lang => lang, :profile => profile, :prefix => prefix}
      - if base || title
        %head
          - if base
            %base{:href => base}
          - if title
            %title= title
      %body
        - subjects.each do |subject|
          != yield(subject)
    

    This template takes locals lang, profile, prefix, base, title in addition to subjects to create output similar to the following:

    <!DOCTYPE html>
    <html prefix='xhv: http://www.w3.org/1999/xhtml/vocab#' xmlns='http://www.w3.org/1999/xhtml'>
      <head>
        <base href="http://example/">
        <title>Document Title</title>
      </head>
      <body>
        ...
      </body>
    </html>
    

    Options passed to the Writer are used to supply lang, profile and base locals. prefix is generated based upon prefixes found from default or supplied profiles, as well as those provided by a previous Reader. title is taken from the first top-level subject having an appropriate title property (as defined by the heading_predicates option).

  • subject: Subject Template, take a subject and an order list of _predicate_s and yields each predicate to be rendered. Described further in {RDF::RDFa::Writer#render_subject}.

    - if element == :li
      %li{:about => get_curie(subject), :typeof => typeof}
        - if typeof
          %span.type!= typeof
        - predicates.each do |predicate|
          != yield(predicate)
    - elsif rel && typeof
      %div{:rel => get_curie(rel)}
        %div{:about => get_curie(subject), :typeof => typeof}
          %span.type!= typeof
          - predicates.each do |predicate|
            != yield(predicate)
    - elsif rel
      %div{:rel => get_curie(rel), :resource => get_curie(subject)}
        - predicates.each do |predicate|
          != yield(predicate)
    - else
      %div{:about => get_curie(subject), :typeof => typeof}
        - if typeof
          %span.type!= typeof
        - predicates.each do |predicate|
          != yield(predicate)
    

    The template takes locals rel and typeof in addition to predicates and subject to create output similar to the following:

    <div about="http://example/">
      ...
    </div>
    

    Note that if typeof is defined, in this template, it will generate a textual description.

  • property_value: Property Value Template, used for predicates having a single value; takes a predicate, and a single-valued Array of objects. Described further in {RDF::RDFa::Writer#render_property}.

    - object = objects.first
    - if heading_predicates.include?(predicate) && object.literal?
      %h1{:property => get_curie(predicate), :content => get_content(object), :lang => get_lang(object), :datatype => get_dt_curie(object)}&= get_value(object)
    - else
      %div.property
        %span.label
          = get_predicate_name(predicate)
        - if res = yield(object)
          != res
        - elsif object.node?
          %span{:resource => get_curie(object), :rel => get_curie(predicate)}= get_curie(object)
        - elsif object.uri?
          %a{:href => object.to_s, :rel => get_curie(predicate)}= object.to_s
        - elsif object.datatype == RDF.XMLLiteral
          %span{:property => get_curie(predicate), :lang => get_lang(object), :datatype => get_dt_curie(object)}<!= get_value(object)
        - else
          %span{:property => get_curie(predicate), :content => get_content(object), :lang => get_lang(object), :datatype => get_dt_curie(object)}&= get_value(object)
    

    In addition to predicate and objects, the template takes locals property and/or rel, which are copies of predicate and indicate use in the @property or @rel attributes. Either or both may be specified, as the conditions dictate.

    Also, if the predicate is identified as a heading predicate (via :heading_predicates option), it will generate a heading element, and may use the value as the document title.

    Each object is yielded to the calling block, and the result is rendered, unless nil. Otherwise, rendering depends on the type of object. This is useful for recursive document descriptions.

    Creates output similar to the following:

    <div class='property'>
      <span class='label'>
        xhv:alternate
      </span>
      <a href='http://rdfa.info/feed/' rel='xhv:alternate'>http://rdfa.info/feed/</a>
    </div>
    

    Note the use of methods defined in {RDF::RDFa::Writer} useful in rendering the output.

  • property_values: Similar to property_value, but for predicates having more than one value. Locals are identical to property_values, but objects is expected to have more than one value.

    %div.property
      %span.label
        = get_predicate_name(predicate)
      %ul{:rel => (get_curie(rel) if rel), :property => (get_curie(property) if property)}
        - objects.each do |object|
          - if res = yield(object)
            != res
          - elsif object.node?
            %li{:resource => get_curie(object)}= get_curie(object)
          - elsif object.uri?
            %li
              %a{:href => object.to_s}= object.to_s
          - elsif object.datatype == RDF.XMLLiteral
            %li{:lang => get_lang(object), :datatype => get_curie(object.datatype)}<!= get_value(object)
          - else
            %li{:content => get_content(object), :lang => get_lang(object), :datatype => get_dt_curie(object)}&= get_value(object)
    

    In this case, and unordered list is used for output. Creates output similar to the following:

    <div class='property'>
      <span class='label'>
        xhv:bookmark
      </span>
      <ul rel='xhv:bookmark'>
        <li>
          <a href='http://rdfa.info/2009/12/12/oreilly-catalog-uses-rdfa/'>
            http://rdfa.info/2009/12/12/oreilly-catalog-uses-rdfa/
          </a>
        </li>
          <a href='http://rdfa.info/2010/05/31/new-rdfa-checker/'>
            http://rdfa.info/2010/05/31/new-rdfa-checker/
          </a>
        </li>
      </ul>
    </div>
    

    If property_values does not exist, repeated values will be replecated using property_value.

  • Type-specific templates. To simplify generation of different output types, the template may contain a elements indexed by a URI. When a subject with an rdf:type matching that URI is found, subsequent Haml definitions will be taken from the associated Hash. For example:

    { :document => "...", :subject => "...", :property_value => "...", :property_values => "...", RDF::URI("http://schema.org/Person") => { :subject => "...", :property_value => "...", :property_values => "...", } }

Dependencies

Documentation

Full documentation available on RubyForge

Principle Classes

  • {RDF::RDFa::Format}
    • {RDF::RDFa::HTML} Asserts :html format, text/html mime-type and .html file extension.
    • {RDF::RDFa::XHTML} Asserts :html format, application/xhtml+xml mime-type and .xhtml file extension.
    • {RDF::RDFa::SVG} Asserts :svg format, image/svg+xml mime-type and .svg file extension.
  • {RDF::RDFa::Reader}
  • {RDF::RDFa::Profile}
  • {RDF::RDFa::Writer}

Additional vocabularies

  • {RDF::PTR}
  • {RDF::RDFA}
  • {RDF::XHV}
  • {RDF::XML}
  • {RDF::XSI}

TODO

  • Add support for LibXML and REXML bindings, and use the best available
  • Consider a SAX-based parser for improved performance

Resources

Author

Contributors

Contributing

  • Do your best to adhere to the existing coding conventions and idioms.
  • Don't use hard tabs, and don't leave trailing whitespace on any line.
  • Do document every method you add using YARD annotations. Read the tutorial or just look at the existing code for examples.
  • Don't touch the .gemspec, VERSION or AUTHORS files. If you need to change them, do so on your private branch only.
  • Do feel free to add yourself to the CREDITS file and the corresponding list in the the README. Alphabetical order applies.
  • Do note that in order for us to merge any non-trivial changes (as a rule of thumb, additions larger than about 15 lines of code), we need an explicit public domain dedication on record from you.

License

This is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying {file:UNLICENSE} file.

FEEDBACK