<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta>
      <journal-title-group>
        <journal-title>April</journal-title>
      </journal-title-group>
    </journal-meta>
    <article-meta>
      <title-group>
        <article-title>SparqPlug: Generating Linked Data from Legacy HTML, SPARQL and the DOM</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Peter Coetzee</string-name>
          <email>plc06@doc.ic.ac.uk</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Tom Heath</string-name>
          <email>tom.heath@talis.com</email>
          <xref ref-type="aff" rid="aff2">2</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Enrico Motta</string-name>
          <email>e.motta@open.ac.uk</email>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Department of Computing, Imperial College London, 180 Queen's Gate</institution>
          ,
          <addr-line>London, SW7 2AZ</addr-line>
          ,
          <country country="UK">United Kingdom</country>
        </aff>
        <aff id="aff1">
          <label>1</label>
          <institution>Knowledge Media Institute, The Open University</institution>
          ,
          <addr-line>Walton Hall, Milton Keynes, MK7 6AA</addr-line>
          ,
          <country country="UK">United Kingdom</country>
        </aff>
        <aff id="aff2">
          <label>2</label>
          <institution>Talis Information Ltd</institution>
          ,
          <addr-line>Knights Court, Solihull, Parkway, Birmingham, Business Park, B37 7YB</addr-line>
          ,
          <country country="UK">United Kingdom</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2008</year>
      </pub-date>
      <volume>22</volume>
      <issue>2008</issue>
      <abstract>
        <p>The availability of linked RDF data remains a significant barrier to the realisation of a Semantic Web. In this paper we present SparqPlug, an approach that uses the SPARQL query language and the HTML Document Object Model to convert legacy HTML data sets into RDF. This framework improves upon existing approaches in a number of ways. For example, it allows the DOM to be queried using the full flexibility of SPARQL and makes converted data automatically available in the Semantic Web. We outline the process of batch conversion to RDF using SparqPlug and illustrate this with a case study. The paper concludes with an examination of factors affecting SparqPlug's performance across various forms of HTML data.</p>
      </abstract>
      <kwd-group>
        <kwd>eol&gt;RDF</kwd>
        <kwd>SPARQL</kwd>
        <kwd>DOM</kwd>
        <kwd>HTML</kwd>
        <kwd>Conversion</kwd>
        <kwd>Linked Data</kwd>
        <kwd>Semantic Web</kwd>
        <kwd>Data Mining</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. INTRODUCTION</title>
      <p>One of the ongoing challenges facing the Semantic Web is not a
technical one, but rather a human one; many data providers will
not be motivated to make their data available on the Web in formats
that are useful to Semantic Web clients (i.e. RDF) until such clients
are widely deployed and used. Similarly, these clients are unlikely
to become popular until sufficient instance data is available to offer
compelling utility value.
∗This work was conducted while the author was a member of KMi,
The Open University.
†This work was conducted while the author was a member of KMi,
The Open University.</p>
      <p>
        For this reason, many Semantic Web-aware developers have an
interest in converting existing non-RDF datasets into RDF models for
publication on the Web. A noteworthy example of such an effort
is the DBpedia Project [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ], which has the aim of making existing
template-structured data within Wikipedia [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] available on the Web
as crawlable Linked Data, and queryable via a SPARQL[
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]
endpoint. The size of Wikipedia justifies a large-scale custom solution
for this conversion, however many smaller datasets will not warrant
such an approach despite the value of their data.
      </p>
      <p>
        To address these issues we have developed SparqPlug, a generic
framework for converting legacy HTML-only datasets into RDF,
and making this data available on the Web. The SparqPlug
approach is targeted at more sophisticated Semantic Web
practitioners, and as such requires a fair degree of domain-specific
knowledge to be useful. One goal of the approach is to enable the reuse
of existing skills that one may expect developers in the Semantic
Web field to hold, such as writing SPARQL[
        <xref ref-type="bibr" rid="ref3">3</xref>
        ] queries.
Two key processes underlie the SparqPlug approach: parsing the
DOM of an HTML document and converting this to RDF, then
querying the resulting graph using SPARQL to extract the desired
data. A number of existing techniques attempt to extract RDF from
legacy HTML data sources. In the following section we will
review this existing work, before examining the SparqPlug approach
in detail. Later sections of the paper present a case study, using
SparqPlug to RDFize example datasets, and a brief evaluation of
the system’s performance.
2.
      </p>
    </sec>
    <sec id="sec-2">
      <title>RELATED WORK</title>
    </sec>
    <sec id="sec-3">
      <title>2.1 DOM, XSLT, and GRDDL</title>
      <p>
        The Document Object Model has long been the favored means
amongst developers for accessing the parse tree of HTML and XML.
It provides methods for getting the attributes and children of nodes,
making processing of the tree less difficult and cumbersome than
manual parsing. However, it is in general too complicated a method
for converting a given document tree into another. For this, XML
stylesheets and transformations (in the form of XSLT) are the
accepted standard, as embodied in the GRDDL approach [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ]. While
this is significantly easier to use, it is by no means perfect. One
of its greatest limitations is the extent to which it requires perfect
lexical representation: the slightest syntactic bug or inconsistency
in the source document, or even syntactically correct but misused
XSLT tags, and the entire operation will fail. It is challenging to
craft a transformation for a given set of source documents, and can
even be impossible to convert regular HTML with an XSLT without
first serializing it as valid XHTML.
technologies as SparqPlug. Its output is held locally as an RDF
silo.
      </p>
      <p>
        The SparqPlug approach also requires the use of valid syntax; but
should make it far simpler to successfully query the DOM. Part of
its operation involves the parsing of the HTML DOM through a
Tidy-esque system to balance tags and validate the model. This at
least adresses one of the issues outlined with XSLT; why not just
serialise this DOM to valid XHTML, and continue accordingly?
The shortcomings of XSLT have given rise to XQuery as an
alternate means of extracting data from the DOM. Some have even
attempted to convert SPARQL queries into a valid XSLT / XQuery
syntax, to query the DOM directly [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ]. While these type of
approaches are very simple, and generally rely on standard tools, they
lack the full expressivity of the SPARQL language. Integrally, the
standards they rely on ignore some key implementation specific
extensions (as suggested, albeit not required, in the SPARQL spec),
such as ARQ’s[
        <xref ref-type="bibr" rid="ref8">8</xref>
        ] Property Functions[
        <xref ref-type="bibr" rid="ref9">9</xref>
        ].
      </p>
      <p>
        An alternate approach, SPAT[
        <xref ref-type="bibr" rid="ref10">10</xref>
        ], involves extending SPARQL’s
triple pattern syntax to include a mapping (defined in-query)
between a given RDF predicate, and an XPath expression, in order
to facilitate conversion of both RDF to XML and XML to RDF.
One major issue with this latter approach is that of URI minting; it
does not provide a simple way of minting URIs for the document,
instead relying on static URIs, or blank nodes on which to root its
statements.
      </p>
      <p>
        The goal of the SparqPlug system is to facilitate the conversion
of DOM documents, in particular poorly constructed HTML, into
linked RDF data in as simple and automated a manner as possible.
2.2 Data Mining &amp; NLP Techniques
Researchers such as Welty [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ] apply Data Mining techniques from
the Artificial Intelligence field to the problem, with varying degrees
of success. Given the general lack of provenance and trust
awareness in many Semantic Web browsers today, the inherent
inaccuracy of this method can be a major issue; slightly inaccurate
assertions can be more of a hindrance to machine understanding than a
help.
      </p>
    </sec>
    <sec id="sec-4">
      <title>2.3 Thresher</title>
      <p>
        The Thresher [
        <xref ref-type="bibr" rid="ref12">12</xref>
        ] system aims to make the process of conversion
into RDF as easy as possible, so that even the “Average Joe” user
can use it. As a result (by the authors’ own admission), it may not
be as expressive as other methods. It invites a user to markup a
page, extrapolating a pattern in the HTML by analyzing the
distance between DOM edit trees. It provides its output to a user
through the Haystack semantic web interface. All data produced
is held locally in an RDF ‘silo’1.
      </p>
    </sec>
    <sec id="sec-5">
      <title>2.4 MindSwap Web Scraper</title>
      <p>
        Web Scraper [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ], from MindSwap, is perhaps the system closest
in approach to SparqPlug. It allows users to define the structure
of an HTML List or Table in a desktop Java application, and parse
these into RDF through their Ontology Browser. It is more
expressive than Thresher, but will be much harder (or even impossible) to
use with slightly less formally structured data. It requires that its
users have much the same level of knowledge about semantic web
1The term RDF ‘silo’, generally refers to a collection of RDF
instance data which is not linked to any other data sources.
      </p>
    </sec>
    <sec id="sec-6">
      <title>2.5 Piggy Bank</title>
      <p>
        SIMILIE’s Piggy Bank [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] semantic web browser has a
Javascriptbased plugin system for scrapers. It encourages interested parties to
develop and host their HTML scrapers in Javascript, providing the
RDF back to Piggy Bank. It is probably one of the most expressive
of the RDFizers here, as it requires developers to write code to
parse HTML pages. However, a new Javascript application must
be written for each site it is applied to. Piggy Bank also requires
that the developer have knowledge of Javascript as well as related
Semantic Web technologies, effectively closing the door to a large
part of the community. All of the screen scrapers’ output is held in
a local silo, preventing links from this RDF to other data sources.
      </p>
    </sec>
    <sec id="sec-7">
      <title>2.6 Sponger &amp; Triplr</title>
      <p>
        Virtuoso Sponger [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ] and Beckett’s Triplr [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ] work on a
similar ‘RDF Middleware’ style approach. Triplr seeks out GRDDL
[
        <xref ref-type="bibr" rid="ref6">6</xref>
        ] and RSS data from a given (X)HTML page and converts it into
RDF/XML, N-Triples, JSON etc. Virtuoso takes this a step
further; given a URI, it will first attempt to dereference it to obtain
RDF (through content negotiation with an accept: header, as
well as following HTML link elements). Should this fail, it will
try to convert the data source using microformats [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ], RDFa [
        <xref ref-type="bibr" rid="ref18">18</xref>
        ],
eRDF [
        <xref ref-type="bibr" rid="ref19">19</xref>
        ], HTML’s own metadata tags, the HTTP headers from
the server, and even APIs such as Google Base [
        <xref ref-type="bibr" rid="ref20">20</xref>
        ], Flickr [
        <xref ref-type="bibr" rid="ref21">21</xref>
        ]
and del.icio.us [
        <xref ref-type="bibr" rid="ref22">22</xref>
        ]. The obvious limitation of such middleware
services is that they require that the source data be already marked
up for conversion into a machine understandable format, or have
hard-coded access methods (in the case of the Sponger’s API
extraction).
      </p>
    </sec>
    <sec id="sec-8">
      <title>2.7 Round-Up</title>
      <p>
        One of the great disadvantages common to the existing techniques
is that of duplication of effort. Often a single user will use the
application locally, creating their own personal RDF silo. If another
user wishes to convert the same source, they must go through the
process (however simple or complex it may be) all over again.
Furthermore, the data which is produced is, by its local nature, not
necessarily ‘good linked data’, according to the accepted Linking
Open Data community best practices [
        <xref ref-type="bibr" rid="ref23">23</xref>
        ].
      </p>
    </sec>
    <sec id="sec-9">
      <title>3. SPARQPLUG</title>
      <p>
        SparqPlug aims to ease the creation of RDF data from legacy
HTML-only data sources, and make the resulting data available on
the (Semantic) Web. This is achieved by treating the DOM as just
another data source to be queried using the SPARQL query
language. As the system is targeted at creation of RDF models for
exposure on the Semantic Web, it is important that it is
accessible to people familiar with these technologies. As such, its design
incorporates the SPARQL query language [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ] as its means of
deriving RDF models from the source data. It is important to note
that SparqPlug aims to facilitate this conversion across a particular
subset of the process; its area of specialty is the actual conversion
of an HTML document into RDF. Previous authors have already
researched techniques for ontology selection (for example in
Protégé 2000[
        <xref ref-type="bibr" rid="ref4">4</xref>
        ]), and UI based extraction (e.g. Huynh’s Sifter[
        <xref ref-type="bibr" rid="ref5">5</xref>
        ]).
SparqPlug would benefit from integration with such technologies
to further simplify its use.
2. Parse HTML into the Document Object Model in Memory
3. Convert DOM to an RDF Model
4. Query RDF model with a SPARQL CONSTRUCT query
5. Store output model in persistent storage
SparqPlug will be provided as free downloadable software to run
on a local machine, and as a web service online (at
&lt;http://sparqplug.rdfize.com/&gt;), where users may
queue up jobs for execution. The major advantage offered by the
SparqPlug online service is that data can immediately be made
available on the Semantic Web and interlinked with other data sets
from the point of conversion.
      </p>
    </sec>
    <sec id="sec-10">
      <title>3.1 SparqPlug Architecture</title>
      <p>SparqPlug consists of four main components (Fig. 1):
1. SparqPlug DOM2RDF
2. SparqPlug DOM2SPARQL
3. SparqPlug Query Builder
4. SparqPlug Service Engine</p>
    </sec>
    <sec id="sec-11">
      <title>3.2 SparqPlug DOM2RDF</title>
      <p>In many respects, this is the heart of the SparqPlug system. It is
responsible for getting regular real-world HTML and transforming it
into an RDF model in the SparqPlug dom:
(&lt;http://sparqplug.rdfize.com/ns/dom/&gt;)
namespace. It makes use of the following properties when doing
this; note that many of these are taken directly from the DOM itself,
and share the same semantics. Others are added by SparqPlug to
make it easier to query the model. SparqPlug also
incorporates dynamic namespaces for tags:
(&lt;http://sparqplug.rdfize.com/ns/tags/&gt;) and attr:
(&lt;http://sparqplug.rdfize.com/ns/attr/&gt;). These
are for the node names and attribute names respectively.
1. dom:nodeName The DOM Name of the current node, e.g.</p>
      <p>tags:li or tags:body
2. dom:nodeValue The value of this node. For example, a
fragment such as &lt;div&gt;Hello World&lt;/div&gt; has
nodeValue "Hello World"
3. dom:hasAttributes The object of this property is a
BlankNode describing the attributes applied to this node, in
the attr: namespace.
4. dom:subNode An immediate child node of this one in the
parse tree
5. dom:nodeIndex An identifier which is unique for this node
in the entire model
6. dom:subNodeNo An identifier which is unique amongst
siblings of a single parent, a convenience property
7. dom:nextSibling Another convenience property, this
‘points’ to the sibling to the ‘right’ of the current node in
the parse tree
The conversion process recursively walks the DOM, adding
statements for each node under these properties. This model itself is
unsuitable for serving as linked data, as (by necessity) it makes
extensive use of BlankNodes, and is, in addition, of a structure poorly
related to its content data. Each node in the original DOM becomes
a BlankNode in the output graph.</p>
    </sec>
    <sec id="sec-12">
      <title>3.3 SparqPlug DOM2SPARQL</title>
      <p>This component of SparqPlug complements the DOM2RDF
processor. It takes a fragment of HTML as input and follows a
similar conversion procedure as that used to convert the DOM to RDF.
However, instead of using the fragment to create an RDF graph,
DOM2SPARQL uses it to create a SPARQL query for extracting
the target data from the RDF graph generated by DOM2RDF. (This
is often a useful starting point for a user to build their own queries;
it may not always create an optimal query, and its results may not be
complete - but it is designed to be significantly easier than starting
from scratch.)
Integral to DOM2SPARQL is the ability to insert the variables you
wish to use to construct your RDF within the HTML fragment, as
well as inserting required literal values. For example, the fragment
&lt;a href="?someLink"&gt;"Previous Page"&lt;/a&gt; will
produce a SPARQL SELECT query which gets the href of any
hyperlink with the text Previous Page. If the quotation marks were left
off, it would have matched any hyperlink.</p>
      <p>This conversion process from HTML fragment to SPARQL query
is far from trivial; it uses a set of heuristics to produce what aims
to be a minimal and correct SPARQL query for the input fragment.
To do this, it first converts the fragment into a full RDF model
using the DOM2RDF component previously described; in this way
all normalisations and tidyings that are applied to the input
document are also incorporated. This RDF model is then
heuristically trimmed and simplified, node by node. Any triples which
are deemed to be unnecessary constraints are removed. Some of
the heuristics which are applied include:
1. Remove non-constraining values from nodes; node values
describing a SPARQL variable, starting in ’?’, or enclosed
in double-quotes (a SPARQL literal constraint) are kept, and
others are removed
2. Remove nodes entirely which have no children, no value
constraints, and no attributes.
3. Remove dom:hasAttributes predicates from nodes where
the number of attributes is zero.
4. Remove dom:subNodeNo predicates from nodes which have
no siblings in the model.
5. Remove dom:subNode constraints for children which do
not exist (e.g. if the child was a non-constraining node and
was removed).
6. Ensure, to the greatest possible extent, that nodes in the query
follow the order in which they will be encountered in the
RDF model; through experimentation it was determined that
this can afford a 20x increase in execution speed. This
ordering was achieved by ensuring that the basic graph patterns in
the query are created as their relevant portions of RDFized
HTML are processed.</p>
      <p>As SPARQL is a declarative pattern-matching query language, the
more constraints that can be removed, the faster the queries will
run. For this reason, DOM2SPARQL may occasionally be
overzealous in removing constraints – it is anticipated that users will be
more likely to add these constraints back in, increasing the
accuracy of their query, than to remove large numbers of unnecessary
ones.</p>
    </sec>
    <sec id="sec-13">
      <title>3.4 SparqPlug Query Builder</title>
      <p>The Query Builder binds together the features of the
DOM2SPARQL and DOM2RDF components to allow a user to
prototype their queries, before designing a job for the service to
work on. This is usually the best starting point for working with
and getting the most out of the SparqPlug web service. It will
allow a user to test and optimise their queries before submitting them
for processing. It also generates and facilitates testing of a
boilerplate query to extract links from an HTML page.</p>
    </sec>
    <sec id="sec-14">
      <title>3.5 SparqPlug Service Engine</title>
      <p>The final part of SparqPlug is its engine. This does most of the
hard work in the system, gluing together all of the components into
a usable web service. Once the user has worked out her queries,
and found the data she wishes to RDFize, she may setup a new job
for SparqPlug. It is the engine’s responsibility to create and manage
these jobs, and ensure they are processed quickly and fairly. Users
may view the current job queue at any time, or view the status of
their job; this will tell them how much work the engine has done
already, how much it knows it still has to do, or indeed whether or
not the job is complete.</p>
      <p>SparqPlug requires a few pieces of information from a user in
order to process a job. The most important of these are the
prototypical extraction query, and the link query. The former of these
is used to CONSTRUCT an RDF graph from the input document.
No other SPARQL query type is allowed for this field.
SparqPlug can also apply the same extraction query to a set of HTML
documents, specified using the link SPARQL query (SELECT or
SELECT DISTINCT). This is also run over the input document,
and any variables which it SELECTs are added to the job’s work
queue.</p>
      <p>The only other pieces of information presently required are a seed
URL, a job name, and a regular expression to transform the page
URL into the graph name’s local-part. Named graphs
are given names in the namespace
&lt;http://sparqplug.rdfize.com/jobs/&lt;YourJobName&gt;
/graphs/&lt;GraphName&gt;&gt;, and will be dereferencable at that
URI. Group 1 from the regular expression is taken as the local part
(&lt;GraphName&gt;) of the URI.</p>
    </sec>
    <sec id="sec-15">
      <title>3.6 The End Result</title>
      <p>As a job finishes each unit of work it must do, it commits the
results to the graph store, as a collection of named graphs for this job.
The job will have a URI, such as
&lt;http://sparqplug.rdfize.com/jobs/MyJob&gt;, and all
of the graphs belonging to this job will exist in the job’s own graphs
namespace,
&lt;http://sparqplug.rdfize.com/jobs/MyJob/graphs/&gt;.
The organisation of these graphs are up to the user’s Regular
Expression query. If two pages are RDFized and result in having the
same named graph, the output will be the union of the CONSTRUCTed
models.
3.6.1 Linked Data Compliance
Wherever possible, SparqPlug will serve up RDF data according
to the Linking Open Data Community’s accepted best practices.
URIs should be dereferencable, with content negotiation handled
by 303-redirects. At the present time, SparqPlug supports content
negotiation over the MIME types for HTML, RDF/XML, and N3.
If a user-agent requests the URI of the job, it will be served a
description of that job, including details of any graphs it contains.
Dereferencing the /graphs namespace of a job will return the
union-graph of all the named graphs in the job’s dataset. Finally,
one may dereference Things within a job’s graphs, either as
&lt;http://sparqplug.rdfize.com/jobs/MyJob/graphs
/SomeGraph/things/SomeThing&gt;, to get the information
about SomeThing in a specified named graph (SomeGraph), or
&lt;http://sparqplug.rdfize.com/jobs/MyJob/things
/SomeThing&gt;, to get the information about SomeThing
in all graphs in a dataset. Note that the
SomeThing which is described is the URI resource
minted by the SparqPlug job as
&lt;http://sparqplug.rdfize.com/jobs/MyJob/things
/SomeThing&gt;; the addition of /graphs/SomeGraph/things
/SomeThing is merely an added convenience. These RDF
descriptions are simply obtained by means of a SPARQL DESCRIBE
query over the dataset – without any prior knowledge of the data to
be put in the store, it is not possible to provide any more intelligent
descriptions.</p>
      <p>In order to connect RDF output produced by SparqPlug into a Web
of data, links can be made to external data sets at extraction-time.
Where an item’s URI in an external data set can be derived from
some variable within the extracted data, the target URI used in an
RDF link can be minted using the fn:mint property function
described below. Where this is not the case, additional property
functions would need to be defined in order to perform lookups of target
URIs for such links.</p>
    </sec>
    <sec id="sec-16">
      <title>4. MAINTENANCE</title>
      <p>
        For many data sources, it is not sufficient to simply RDFize them
once; they may change frequently. Therefore, it is important that
SparqPlug is able to maintain a degree of accuracy in its data. To
facilitate this, it records an SHA-512 message digest of each
document it downloads and RDFizes. When a maintenance job is run, it
is possible for the job worker to check a page for changes by
comparing the digest of the page with that stored in the graph metadata
store. If they differ, the page has been altered and SparqPlug knows
to rerun the protoypical query over it. This is one of the issues in
allowing a user to describe multiple input documents in the same
named graph; if one of the documents is updated, it is unclear as
to the best course of action. Either the entire graph must be
regenerated, as there is no statement-level provenance information
alongside them, or the data must be left intact, and only new data
added to the store. The SparqPlug maintenance system opts for the
latter approach, based on the principle that ‘disappearing data’ is to
be avoided wherever possible, and that “Cool URIs don’t change”
[
        <xref ref-type="bibr" rid="ref24">24</xref>
        ]. The link query is executed for all documents run through the
maintenance systems, in order to find any new pages that may have
been added to this input set since the last RDFization was carried
out.
      </p>
      <p>
        At any time a user may request that a job’s data is ‘refreshed’, by
visiting its status page on the SparqPlug website. If the job has
finished executing, then it will be queued in the regular work queue
for processing.
5. IMPLEMENTATION DETAILS
5.1 Prototyping
Initial prototyping of the SparqPlug system was performed with
RAP, the RDF API for PHP [
        <xref ref-type="bibr" rid="ref25">25</xref>
        ]. While this was an excellent
solution for rapid development and proof-of-concept, it proved to lack
the performance required for such an application. In particular,
the SPARQL engine was approximately 10x slower than alternative
implementations for slightly more complex queries: complex
RDFization of a DOM Document could be done in approximately 90
seconds in ARQ [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ], as opposed to 1.5 hours in RAP’s MemModel
SPARQL engine.
5.2 Final Selection of Technologies
The final SparqPlug system has been implemented in the Java
programming language, selected for its efficiency, scalability, and
portability. The RDF API, SPARQL, and graph persistence facilities
are provided by the Jena Semantic Web Framework [
        <xref ref-type="bibr" rid="ref26">26</xref>
        ].
SparqPlug uses the NG4J extension to the Jena Framework for
supporting Named Graphs and Datasets [
        <xref ref-type="bibr" rid="ref27">27</xref>
        ]. ARQ [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ], the SPARQL
engine for Jena, offers so-called ’property functions’ [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ], in SPARQL
queries. These are not explicitly specified by the DAWG (the W3C
Data Access Working Group), but can be considered similar to
describing custom inference over a model at query-time. Property
Functions to allow users to concatenate strings, match regular
expressions, and mint URIs have been added to the ARQ library for
SparqPlug, in order to allow users to use these powerful constructs
in their queries to produce higher quality RDF linked data.
many (but not all) of the W3C-specified DOM functions. The web
service is capable of being run in any J2EE compliant servlet
container (it makes use of connection pooling and Filter APIs provided
by the J2EE spec), and is presently run within Apache Tomcat
[
        <xref ref-type="bibr" rid="ref29">29</xref>
        ]. Similarly, any JDBC-compliant database server may be used;
MySQL [
        <xref ref-type="bibr" rid="ref30">30</xref>
        ] is the current database of choice, for scalability and
ease of deployment.
      </p>
    </sec>
    <sec id="sec-17">
      <title>5.3 Scalability</title>
      <p>
        The job processing code runs separately to the web service, as a
simple command line application. It has been designed to operate
concurrently, making use of Jena’s inbuilt locking and concurrency
support. In this way the SparqPlug system can be scaled up to
run on any number of servers; the database and application
containers support server clustering, and separate instances of the job
dispatcher may run concurrently over this database. A single
instance of the job dispatcher may also multithread across multiple
jobs on a single server. In this way, the application is ready to scale
along whichever parameters are required without modification to
its code.
6. CASE STUDY: SPARQPLUG IN ACTION
The SparqPlug system has, as a stated goal, the aim of making the
RDFization process simpler for DOM documents. The extent to
which this has been a success can be examined through sample use
of the system. Due to its nature, it requires a fair degree of Semantic
Web-related knowledge to be usable. A user will be able to craft the
most efficient and accurate queries only after some experience with
the system. In the following example, we will RDFize the database
of TimeOut Films [
        <xref ref-type="bibr" rid="ref31">31</xref>
        ], as a sample data source.
      </p>
      <p>The HTML describing films in these pages follows a repeating
tabular structure, making it particularly suitable for RDFization. For
example:
&lt;tr class=""&gt;
&lt;td&gt;&lt;ul class="bullets"&gt;
&lt;li&gt;
&lt;a href="/film/reviews/
69923/cry-freedom.html"&gt;</p>
      <p>
        Cry Freedom&lt;/a&gt; (1987)
&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
Once we, as a user, have ascertained the structure of the HTML,
we may enter our fragment into the Query Builder. Continuing this
example, we may wish to attempt to make the query as simple as
possible, so describe the films as:
&lt;ul class="bullets"&gt;
&lt;li&gt;&lt;a href="?review"&gt;?title&lt;/a&gt;?date&lt;/li&gt;
&lt;/ul&gt;
This will create us the following prototypical query:
The DOM library selected is JTidy [
        <xref ref-type="bibr" rid="ref28">28</xref>
        ], one of a number of
opensource tag balancing and tidying libraries. It describes itself as a
Java implementation of the standard HTML Tidy, implementing
PREFIX apf:
&lt;java:com.hp.hpl.jena.query.pfunction.library.&gt;
PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX fn:
&lt;java:com.rdfize.functions.&gt;
SELECT ?review ?title ?date
WHERE
{ ?nodeID8 dom:nodeName tags:ul;
dom:subNode ?nodeID9;
dom:hasAttributes _:b1.
_:b1 attr:class "bullets".
?nodeID9 dom:nodeName tags:li;
dom:subNode ?nodeID10;
dom:subNode ?nodeID14.
?nodeID10 dom:nodeName tags:a;
dom:subNodeNo "1";
dom:subNode ?nodeID11;
dom:hasAttributes _:b0.
_:b0 attr:href ?review.
?nodeID11 dom:nodeName tags:text;
dom:nodeValue ?title.
?nodeID14 dom:nodeName tags:text;
dom:subNodeNo "2";
dom:nodeValue ?date.
      </p>
      <p>}
It is worth noting that it has also constructed our boilerplate link
query, although we shan’t pay attention to this until later. The query
below is a reformatted version of the query, to make it slightly
easier to understand (taking advantage of SPARQL’s syntactic sugar
for querying Collections), as well as for columnar layout purposes.
PREFIX apf:
&lt;java:com.hp.hpl.jena.query.pfunction.library.&gt;
PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX rdf:
&lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
PREFIX rfn:
&lt;java:com.rdfize.functions.&gt;
PREFIX fn:
&lt;http://www.w3.org/2005/xpath-functions#&gt;
SELECT DISTINCT ?linkCon
WHERE
{ ?nodeID8 dom:nodeName tags:a;
dom:hasAttributes _:b0.
_:b0 attr:href ?link.</p>
      <p>{ ?x rfn:cat
("http://www.timeout.com/film/index/film/a/"
?link ).</p>
      <p>?linkCon rfn:mint ?x.</p>
      <p>FILTER (
!( fn:starts-with(?link, "http")
|| fn:starts-with(?link, "/"))
)
}
UNION</p>
      <p>{ ?x rfn:cat
("http://www.timeout.com" ?link).</p>
      <p>?linkCon rfn:mint ?x.</p>
      <p>FILTER fn:starts-with(?link, "/")
}
UNION
{ ?linkCon rfn:mint ?link.</p>
      <p>FILTER fn:starts-with(?link,
"http://www.timeout.com")
}</p>
      <p>}
If we run this RDFization through the Query Builder, we will find
it returns a table of results, as we would expect. However, it takes
approximately three minutes to do so; this is not terrible efficiency,
but it can be improved upon. It may seem counter-intuitive, but by
adding more constraints to a query, we can reduce the number of
cross products ARQ has to construct, and thus improve efficiency
of the query. Furthermore, the above query also matches some
non-film data; while we could FILTER this dirty data out in the
SPARQL query, a more specific query may be able to match more
accurately. Suppose we change our fragment to:
&lt;tr class=""&gt;
&lt;td&gt;
&lt;ul class="bullets"&gt;
&lt;li&gt;
&lt;a href="?review"&gt;?title&lt;/a&gt;?date&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
This will create us the following prototypical query:
PREFIX apf:
&lt;java:com.hp.hpl.jena.query.pfunction.library.&gt;
PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX fn:
&lt;java:com.rdfize.functions.&gt;
SELECT ?review ?title ?date
WHERE
{ ?nodeID8 dom:nodeName tags:table;
dom:subNode ?nodeID9.
?nodeID9 dom:nodeName tags:tr;
dom:subNode ?nodeID10;
dom:hasAttributes _:b2.
_:b2 attr:class "".
?nodeID10 dom:nodeName tags:td;</p>
      <p>dom:subNode ?nodeID11.
?nodeID11 dom:nodeName tags:ul;
dom:subNode ?nodeID12;
dom:hasAttributes _:b1.</p>
      <p>This new query will execute in under a second; a significant
improvement over the old running times. However, it is returning
approximately half the number of results. Returning to the
TimeOut page, we notice that many of the listed films do not have a date
attached. By altering the query to make the ?date clause optional,
we may attain a much better set of results, thus:
PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX fn:
&lt;java:com.rdfize.functions.&gt;
SELECT ?review ?title ?date
WHERE
{ ?nodeID8 dom:nodeName tags:table;
dom:subNode ?nodeID9.
?nodeID9 dom:nodeName tags:tr;
dom:subNode ?nodeID10;
dom:hasAttributes _:b2.
_:b2 attr:class "".
?nodeID10 dom:nodeName tags:td;</p>
      <p>dom:subNode ?nodeID11.
?nodeID11 dom:nodeName tags:ul;
dom:subNode ?nodeID12;
dom:hasAttributes _:b1.
_:b1 attr:class "bullets".
?nodeID12 dom:nodeName tags:li;
dom:subNode ?nodeID13;
dom:subNode ?nodeID17.
?nodeID13 dom:nodeName tags:a;
dom:subNodeNo "1";
dom:subNode ?nodeID14;
dom:hasAttributes _:b0.
_:b0 attr:href ?review.
?nodeID14 dom:nodeName tags:text;
dom:nodeValue ?title.</p>
      <p>OPTIONAL {
?nodeID17 dom:nodeName tags:text;
dom:subNodeNo "2";
dom:nodeValue ?date.
Now that we are able to SELECT a suitable set of results, the next
stage is to construct it into a useful RDF model. To do this, we
will make use of some of the Property Functions developed for
SparqPlug. Some of the desirable alterations to the data would be;
• Minting URIs for each of the films
• Removing the parentheses from around the dates
• Resolving the Review URL to an absolute path
• Minting a URI Resource from the Review URL</p>
    </sec>
    <sec id="sec-18">
      <title>6.1 Minting The Film’s URI</title>
      <p>The basic technique for this will be to first match the film name
out of the review URL, then append the ID number of the film (as
a disambiguation step between films of the same name), putting
it into the SparqPlug namespace, and finally minting it as a URI
Resource. This can be done as in the following SPARQL fragment,
binding ?r to the Resource:
(?m0 ?m1 ?m2) fn:match
( ?review "\\/film\\/reviews</p>
      <p>\\/(.*)\\/(.*)\\.html" ).
?x fn:cat
( "http://sparqplug.rdfize.com
/jobs/TimeOutFilms/things/"
?m2 "-" ?m1 ).</p>
      <p>?r fn:mint ?x.</p>
      <p>However, since this is going to be a regular ‘incantation’ for a user
to employ, a property function, fn:thing, was introduced, along
with a new namespace for URIs. The fn:thing function takes
two parameters as an object-list, and mints a URI as its subject of
the form:
&lt;http://uris.rdfize.com/JobName/LocalName&gt;.
This URI is dereferencable in the typical Linked-Data fashion, and
will 303-redirect a user to the representation they request in the
http://sparqplug.rdfize.com/jobs/ namespace.
Thus, the above query fragment can be altered, removing the onus
of accurate namespace allocation from the user:
(?m0 ?m1 ?m2) fn:match
( ?review "\\/film\\/reviews</p>
      <p>\\/(.*)\\/(.*)\\.html" ).
?local fn:cat ( ?m2 "-" ?m1 ).</p>
      <p>?r fn:thing ( "TimeOutFilms" ?local ).</p>
    </sec>
    <sec id="sec-19">
      <title>6.2 Removing Parentheses</title>
      <p>Having already seen the use of fn:match above, this is a fairly
simple process:
(?y0 ?year) fn:match
(?date "\\((.*)\\)").</p>
    </sec>
    <sec id="sec-20">
      <title>6.4 Putting it together</title>
      <p>
        We now have all of the pieces ready to CONSTRUCT our RDF
model. This is the time we also need to choose the ontology /
ontologies we wish to use to describe the Films. For this example, we
will use the popular Dublin Core [
        <xref ref-type="bibr" rid="ref32">32</xref>
        ] ontology, as well as
statements from the Review Ontology and the RDFS Yago [
        <xref ref-type="bibr" rid="ref33">33</xref>
        ] class
hierarchy hosted by DBpedia [
        <xref ref-type="bibr" rid="ref34">34</xref>
        ].
      </p>
      <p>PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX fn:
&lt;java:com.rdfize.functions.&gt;
PREFIX dc:
&lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX rev:
&lt;http://purl.org/stuff/rev#&gt;
PREFIX yago:
&lt;http://dbpedia.org/class/yago/&gt;
CONSTRUCT {
?r a yago:MotionPictureFilm103789400;
dc:date ?year;
dc:title ?title;
rev:hasReview ?rev.
}
WHERE
{ ?nodeID8 dom:nodeName tags:table;
dom:subNode ?nodeID9.
?nodeID9 dom:nodeName tags:tr;
dom:subNode ?nodeID10;
dom:hasAttributes _:b2.
_:b2 attr:class "".
?nodeID10 dom:nodeName tags:td;
dom:subNode ?nodeID11.
?nodeID11 dom:nodeName tags:ul;
dom:subNode ?nodeID12;
dom:hasAttributes _:b1.
_:b1 attr:class "bullets".
?nodeID12 dom:nodeName tags:li;
dom:subNode ?nodeID13;
dom:subNode ?nodeID17.
?nodeID13 dom:nodeName tags:a;
dom:subNodeNo "1";
dom:subNode ?nodeID14;
dom:hasAttributes _:b0.
_:b0 attr:href ?review.
?nodeID14 dom:nodeName tags:text;
dom:nodeValue ?title.
(?m0 ?m1 ?m2) fn:match (?review
"\\/film\\/reviews\\/(.*)\\/(.*)\\.html"
).
?uc fn:cat (
"http://sparqplug.rdfize.com/jobs</p>
      <p>/TimeOutFilms/things/"
?m2 "-" ?m1 ).
?r fn:mint ?uc.
?rc fn:cat ("http://www.timeout.com"
?review).
?rev fn:mint ?rc.</p>
      <p>OPTIONAL {
?nodeID17 dom:nodeName tags:text;
dom:subNodeNo "2";
dom:nodeValue ?date.
(?y0 ?year) fn:match</p>
      <p>(?date "\\((.*)\\)").
}</p>
      <p>}
This query can be tested against any of the pages in the TimeOut
Films dataset, producing RDF (in under 200ms) for each film
similar to:
&lt;http://sparqplug.rdfize.com/jobs
/TimeOutFilms/things/cry-freedom-69923&gt;
a yago:MotionPictureFilm103789400;
dc:date "1987";
dc:title "Cry Freedom";
rev:hasReview
&lt;http://www.timeout.com/film/reviews
/69923/cry-freedom.html&gt;.</p>
    </sec>
    <sec id="sec-21">
      <title>6.5 Link SPARQL</title>
      <p>The final consideration before designing the job for this is
construction of the link query; the boilerplate query that is generated
will result in crawling the entire TimeOut website, producing a
large number of empty graphs, or worse, bad data. We therefore
want to trim its results down to limit it only to URLs that start in
/film/index/film/, as follows:
PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
PREFIX attr:
&lt;http://sparqplug.rdfize.com/ns/attributes/&gt;
PREFIX rfn:
&lt;java:com.rdfize.functions.&gt;
PREFIX fn:
&lt;http://www.w3.org/2005/xpath-functions#&gt;
SELECT DISTINCT ?link
WHERE
{ ?nodeID8 dom:nodeName tags:a;
dom:hasAttributes _:b0.
_:b0 attr:href ?l.
?x rfn:cat</p>
      <p>( "http://www.timeout.com" ?l ).
?link rfn:mint ?x.</p>
      <p>FILTER fn:starts-with(?l,</p>
      <p>"/film/index/film/")
}
This query will match approximately 30 results from each page;
it is important to note that when run in a job, the query is
executed against each page that is RDFized, so when (as with
TimeOut Films) results are paginated, it will find all of them through the
course of the job’s execution.</p>
    </sec>
    <sec id="sec-22">
      <title>6.6 Designing the SparqPlug Job</title>
      <p>Much of the work in preparing the job is now complete. The job
now only needs to be named and described, and the Graph RegExp
decided upon. This regular expression is used to determine which
named graph the data from each page should be put into. It is
important to note that a separate RDF Dataset exists for each job, so
no named graph collisions will occur between jobs. The default
RegExp,</p>
      <p>^.*/([^/]*)(\.html|\.htm|\.php|\.jsp)$
will use the page’s name for its graph. In this case, that is less
than desirable; it would make more sense to split up the dataset
alphabetically, in exactly the same manner as TimeOut organises
them. Therefore, we will use the following RegExp:</p>
      <p>^.*/([^/]*)/[^/]*\.html$
The job is now ready to be commited and executed. As soon as it is
in the job queue, its URI becomes dereferencable for information
about its progress, and a snapshot of the current RDF available.
Things in the job’s namespaceare also dereferencable as soon as
they are in the dataset.</p>
    </sec>
    <sec id="sec-23">
      <title>7. EVALUATION</title>
      <p>The example job described above was executed on the SparqPlug
web service before launch, as a simple performance indicator.
Including network latency, the full RDFization of a page (GET the
page, extract links and add them to the work queue, CONSTRUCT
the graph, and add the graph to the dataset) takes approximately 5
seconds. The full RDFization of the TimeOut Films dataset took
around 25 minutes, and involved RDFizing 228 HTML pages.
In the interests of fair testing, we proceeded to set up a performance
testing harness. For each of our performance tests, we execute a
SPARQL query against an HTML fragment; in this way we test
both the DOM2RDF and SPARQL Query components of the
system, in order to best simulate the process of a job’s execution. Each
test is repeated five times, and the average execution time taken.
The first test we ran was to quantitively evaluate query execution
with a single query over a varying length of HTML list. The HTML
was constructed as a list of 0 - 1000 elements, as in the following
example snippet:
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Row 0, Text Item 0&lt;/p&gt;
&lt;p&gt;Row 0, Text Item 1&lt;/p&gt;
...................&lt;SNIP&gt;...................
&lt;p&gt;Row 0, Text Item 8&lt;/p&gt;
&lt;p&gt;Row 0, Text Item 9&lt;/p&gt;
&lt;/li&gt;
These data constructs were then each queried with two SPARQL
queries, to extract the paragraph text from within the list items.
The two queries were semantically identical, but one was ordered
intelligently, and the second had its triple patterns put into a random
order. These queries remained constant throughout the tests.</p>
      <p>PREFIX dom:
&lt;http://sparqplug.rdfize.com/ns/dom/&gt;
PREFIX tags:
&lt;http://sparqplug.rdfize.com/ns/tags/&gt;
SELECT ?someValue
WHERE
{
?nodeID8 dom:nodeName</p>
      <p>dom:subNode
?nodeID9 dom:nodeName</p>
      <p>dom:subNode
?nodeID10 dom:nodeName</p>
      <p>dom:subNode
?nodeID11 dom:nodeName
dom:nodeValue
tags:ul;
?nodeID9.
tags:li;
?nodeID10.
tags:p;
?nodeID11.
tags:text;
?someValue.</p>
      <p>}
The results of these tests are represented in Figure 2. These
figures offer some support for the earlier observation that ordering
the triple patterns in the query speeds up the query execution. It
also suggests that the system as a whole scales linearly along with
HTML fragment size.</p>
    </sec>
    <sec id="sec-24">
      <title>8. FUTURE WORK</title>
      <p>The SparqPlug service is fully operational in its present state, and
fulfils many of its original goals. However, learning from others in
this space it may be possible to improve the user experience. One
such area is that of optimisation; it can take an exceptionally long
time for certain queries to execute, particularly those that entail
calculation of large cross products. By using the standard distribution
of ARQ, we have ensured it will be possible to rapidly integrate
future releases and optimisations of the SPARQL engine. Even so,
it may be possible to decrease the amount of work the engine has
to do. With improved understanding of the query planning and
execution within ARQ, it should be possible for the Query Builder to
produce queries which will execute more efficiently. Streamlining
and optimising the RDF model output by the DOM2RDF
component of SparqPlug with this query execution and planning in mind
may also have a positive impact on performance. An alternative
approach to optimisation would be to investigate attaching
different SPARQL query processors and triple stores to the SparqPlug
service.</p>
      <p>Another aspect that could be improved is the user interface. The
ability for a user to click-and-drag to select the area of HTML they
wish to RDFize could, if coupled with query builder enhancements,
allow SparqPlug to combine the ease of use in systems such as
Thresher without reducing its query expressivity in any shape or
form.</p>
      <p>
        A final area that may prove fruitful to expand research into the
SparqPlug approach is that of less formally structured data. SparqPlug
can be very efficient and accurate over highly structured DOM
documents (e.g. lists of entries, rows of tables etc.) It can, however, be
challenging to construct a successful SparqPlug job to, for example,
parse the contents of a wiki page into useful RDF. An expansion of
the property functions available to the SparqPlug engine, perhaps
to normalise the data before processing, may prove valuable here.
Another relevant approach here may be that of embedding custom
property functions[
        <xref ref-type="bibr" rid="ref35">35</xref>
        ] as javascript inside the query.
      </p>
    </sec>
    <sec id="sec-25">
      <title>9. ACKNOWLEDGEMENTS</title>
      <p>This research was partially supported by the OpenKnowledge (OK)
project. OK is sponsored by the European Commission as part
of the Information Society Technologies (IST) programme under
grant number IST-2001-34038.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <surname>Auer</surname>
            ,
            <given-names>S</given-names>
          </string-name>
          ; Bizer,
          <string-name>
            <surname>C</surname>
          </string-name>
          ; Kobilarov,
          <string-name>
            <surname>G</surname>
          </string-name>
          ; Lehmann,
          <string-name>
            <surname>J</surname>
          </string-name>
          ; Cyganiak,
          <string-name>
            <surname>R</surname>
          </string-name>
          ; Ives,
          <string-name>
            <surname>Z</surname>
          </string-name>
          : “
          <article-title>DBpedia: A Nucleus for a Web of Open Data”</article-title>
          .
          <source>In Proc. of the 6th Intl. Semantic Web Conference (ISWC2007)</source>
          , Busan, Korea.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>[2] http://www.wikipedia.org/</mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <surname>Prud'hommeaux</surname>
            , E; Seaborne,
            <given-names>A</given-names>
          </string-name>
          : “
          <article-title>SPARQL Query Language for RDF" http://www</article-title>
          .w3.org/TR/rdf-sparql-query/
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <surname>Gennari</surname>
            ,
            <given-names>J</given-names>
          </string-name>
          ; Musen,
          <string-name>
            <surname>M</surname>
          </string-name>
          ; Fergerson,
          <string-name>
            <surname>R</surname>
          </string-name>
          ; Grosso,
          <string-name>
            <surname>W</surname>
          </string-name>
          ; Crubézy,
          <string-name>
            <surname>M</surname>
          </string-name>
          ; Eriksson,
          <string-name>
            <surname>H</surname>
          </string-name>
          ; Noy,
          <string-name>
            <surname>N</surname>
          </string-name>
          ; Tu,
          <string-name>
            <surname>S: “</surname>
          </string-name>
          <article-title>The evolution of Protégé: an environment for knowledge-based systems development"</article-title>
          . In
          <source>International Journal of Human-Computer Studies (January</source>
          <year>2003</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <surname>Huynh</surname>
            ,
            <given-names>D</given-names>
          </string-name>
          ; Miller,
          <string-name>
            <surname>R</surname>
          </string-name>
          ; Karger,
          <string-name>
            <surname>D</surname>
          </string-name>
          : “
          <article-title>Enabling Web Browsers to Augment Web Sites' Filtering and Sorting Functionalities"</article-title>
          .
          <source>In Proc. of the 19th annual ACM symposium on User interface software and technology</source>
          , Montreux, Switzerland.
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>[6] http://www.w3.org/TR/grddl</mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <surname>Droop</surname>
            ,
            <given-names>M</given-names>
          </string-name>
          ; Flarer,
          <string-name>
            <surname>M</surname>
          </string-name>
          ; Groppe,
          <string-name>
            <surname>J</surname>
          </string-name>
          ; Groppe,
          <string-name>
            <surname>S</surname>
          </string-name>
          ; Linnemann,
          <string-name>
            <surname>V</surname>
          </string-name>
          ; Pinggera,
          <string-name>
            <given-names>J</given-names>
            ;
            <surname>Santner</surname>
          </string-name>
          ,
          <string-name>
            <surname>F</surname>
          </string-name>
          ; Schier,
          <string-name>
            <given-names>M;</given-names>
            <surname>Schoepf</surname>
          </string-name>
          ,
          <string-name>
            <surname>F</surname>
          </string-name>
          ; Staffler,
          <string-name>
            <surname>H</surname>
          </string-name>
          ; Zugal,
          <string-name>
            <surname>S</surname>
          </string-name>
          : “
          <article-title>Translating XPath Queries into SPARQL Queries"</article-title>
          .
          <source>In Proc. of On the Move to Meaningful Internet Systems</source>
          <year>2007</year>
          :
          <article-title>OTM 2007 Workshops</article-title>
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>[8] http://jena.sourceforge.net/ARQ/</mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <surname>Seaborne</surname>
            ,
            <given-names>A</given-names>
          </string-name>
          : ARQTick 13 October 2006 - “
          <article-title>Assignment Property Function"</article-title>
          http://seaborne.blogspot.com/
          <year>2006</year>
          /10/assignment-propertyfunction.html
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>Eric</given-names>
            <surname>Prud</surname>
          </string-name>
          <article-title>'hommeaux: “SPAT - SPARQL Annotations"</article-title>
          http://www.w3.org/
          <year>2007</year>
          /01/SPAT/
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <surname>Welty</surname>
            ,
            <given-names>C</given-names>
          </string-name>
          ; Murdock,
          <string-name>
            <surname>J W:</surname>
          </string-name>
          “
          <article-title>Towards Knowledge Acquisition from Information Extraction"</article-title>
          .
          <source>In Proc. of the 5th Intl. Semantic Web Conference (ISWC2006)</source>
          , Athens, Georgia, USA.
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <surname>Hogue</surname>
            ,
            <given-names>A</given-names>
          </string-name>
          ; Karger,
          <string-name>
            <surname>D</surname>
          </string-name>
          : “
          <article-title>Thresher: automating the unwrapping of semantic content from the World Wide Web”</article-title>
          .
          <source>In Proc. of the 14th Intl. World Wide Web conference (WWW2005)</source>
          , Chiba, Japan.
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <surname>Kalyanpur</surname>
            ,
            <given-names>A</given-names>
          </string-name>
          : “
          <article-title>RDF Web Scraper"</article-title>
          http://www.mindswap.org/~aditkal/rdf.shtml
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>[14] http://simile.mit.edu/wiki/Piggy_Bank</mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>[15] http://openlinksw.com/virtuoso</mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>[16] http://triplr.org</mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>[17] http://microformats.org</mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          [18]
          <string-name>
            <surname>Birbeck</surname>
            ,
            <given-names>M</given-names>
          </string-name>
          ; Pemberton,
          <string-name>
            <surname>S</surname>
          </string-name>
          ; Adida,
          <string-name>
            <surname>B</surname>
          </string-name>
          : “
          <article-title>RDFa Syntax - A collection of attributes for layering RDF on XML languages" http://www</article-title>
          .w3.org/
          <year>2006</year>
          /07/SWD/RDFa/syntax/
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>[19] “ Rdf In Html" http://research.talis.com/2005/erdf/wiki/Main/RdfInHtml</mixed-citation>
      </ref>
      <ref id="ref20">
        <mixed-citation>[20] http://base.google.com</mixed-citation>
      </ref>
      <ref id="ref21">
        <mixed-citation>[21] http://flickr.com</mixed-citation>
      </ref>
      <ref id="ref22">
        <mixed-citation>[22] http://del.icio.us</mixed-citation>
      </ref>
      <ref id="ref23">
        <mixed-citation>
          [23]
          <string-name>
            <surname>Bizer</surname>
            ,
            <given-names>C</given-names>
          </string-name>
          ; Cyganiak,
          <string-name>
            <surname>R</surname>
          </string-name>
          ; Heath,
          <string-name>
            <surname>T</surname>
          </string-name>
          : “
          <article-title>How to Publish Linked Data on the Web” http://sites</article-title>
          .wiwiss.fuberlin.de/suhl/bizer/pub/LinkedDataTutorial/
        </mixed-citation>
      </ref>
      <ref id="ref24">
        <mixed-citation>
          [24]
          <string-name>
            <surname>Sauermann</surname>
            ,
            <given-names>L</given-names>
          </string-name>
          ; Cyganiak,
          <string-name>
            <surname>R</surname>
          </string-name>
          ; Ayers,
          <string-name>
            <surname>D</surname>
          </string-name>
          ; Voelkel,
          <string-name>
            <surname>M:</surname>
          </string-name>
          “
          <article-title>Cool URIs for the Semantic Web"</article-title>
          http://www.w3.org/TR/2007/WD-cooluris-
          <volume>20071217</volume>
          /
        </mixed-citation>
      </ref>
      <ref id="ref25">
        <mixed-citation>
          [25]
          <string-name>
            <surname>Oldakowski</surname>
            ,
            <given-names>R</given-names>
          </string-name>
          ; Bizer,
          <string-name>
            <surname>C</surname>
          </string-name>
          ; Westphal,
          <string-name>
            <surname>D</surname>
          </string-name>
          : “
          <article-title>RAP: RDF API for PHP"</article-title>
          .
          <source>In Proc. of the 1st Workshop on Scripting for the Semantic Web (SFSW2005)</source>
          ,
          <source>2nd European Semantic Web Conference (ESWC2005)</source>
          , Heraklion, Greece
        </mixed-citation>
      </ref>
      <ref id="ref26">
        <mixed-citation>[26] http://jena.sourceforge.net/</mixed-citation>
      </ref>
      <ref id="ref27">
        <mixed-citation>
          [27]
          <string-name>
            <surname>Bizer</surname>
            ,
            <given-names>C</given-names>
          </string-name>
          ; Cyganiak,
          <string-name>
            <surname>R</surname>
          </string-name>
          : “
          <article-title>NG4J - Named Graphs API for Jena"</article-title>
          http://sites.wiwiss.fu-berlin.de/suhl/bizer/ng4j/
        </mixed-citation>
      </ref>
      <ref id="ref28">
        <mixed-citation>[28] http://jtidy.sourceforge.net/</mixed-citation>
      </ref>
      <ref id="ref29">
        <mixed-citation>[29] http://tomcat.apache.org/</mixed-citation>
      </ref>
      <ref id="ref30">
        <mixed-citation>[30] http://www.mysql.org/</mixed-citation>
      </ref>
      <ref id="ref31">
        <mixed-citation>[31] http://www.timeout.com/film/index/film/a/1.html</mixed-citation>
      </ref>
      <ref id="ref32">
        <mixed-citation>[32] http://purl.org/dc/elements/1.1/</mixed-citation>
      </ref>
      <ref id="ref33">
        <mixed-citation>
          [33]
          <string-name>
            <surname>Suchanek</surname>
            ,
            <given-names>F</given-names>
          </string-name>
          ; Kasneci,
          <string-name>
            <surname>G</surname>
          </string-name>
          ; Weikum,
          <string-name>
            <surname>G</surname>
          </string-name>
          : “
          <article-title>Yago - A Core of Semantic Knowledge"</article-title>
          .
          <source>In Proc. of 16th Intl. World Wide Web conference (WWW2007)</source>
          , Banff, Alberta, Canada.
        </mixed-citation>
      </ref>
      <ref id="ref34">
        <mixed-citation>[34] http://dbpedia.org/</mixed-citation>
      </ref>
      <ref id="ref35">
        <mixed-citation>
          [35]
          <string-name>
            <surname>Williams</surname>
            ,
            <given-names>G</given-names>
          </string-name>
          : “
          <article-title>Extensible SPARQL Functions With Embedded Javascript"</article-title>
          .
          <source>From 3rd Workshop on Scripting for the Semantic Web (SFSW2007)</source>
          ,
          <source>4th European Semantic Web Conference (ESWC2007)</source>
          , Innbruck, Austria.
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>