不要使用 XML 库来解析 RDF。它会给你带来痛苦的世界。
另外,永远不要将 XML::Simple 用于任何事情。
RDF::Trine 是 Perl 中 RDF 的最新技术。 Attean 正在编写以替换它,重量更轻,应该提供更好的 API,但还没有真正准备好。
使用 RDF::Trine 的示例
use strict;
use warnings;
use RDF::Trine;
# $base is for resolving any relative URLs.
my $base = 'http://example.com/';
# Parse the data into $model
my $parser = RDF::Trine::Parser::RDFXML->new;
my $model = RDF::Trine::Model->new;
$parser->parse_file_into_model($base, \*DATA, $model);
# Some namespaces for querying the data...
my $oslc = RDF::Trine::Namespace->new('http://open-services.net/xmlns/discovery/1.0/');
my $dc = RDF::Trine::Namespace->new('http://purl.org/dc/terms/');
# Cycle through the objects of oscl_disc:entry
for my $provider ( $model->objects(undef, $oslc->entry) ) {
# Get the title. This returns a list of titles, so we call
# it in list context and get just the first result.
my ($title) = $model->objects($provider, $dc->title);
# Print it.
print "GOT: ", $title->literal_value, "\n";
}
__DATA__
<oslc_disc:ServiceProviderCatalog
xmlns:oslc_disc="http://open-services.net/xmlns/discovery/1.0/"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:jfs_proc="https://jazz.net/xmlns/prod/jazz/process/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
rdf:about="https://localhost:9443/ccm/oslc-scm/catalog.xml"
>
<oslc_disc:entry>
<oslc_disc:ServiceProvider>
<dc:title>Foo Bar Baz</dc:title>
<oslc_disc:details rdf:resource="foo"/>
<oslc_disc:services rdf:resource="bar"/>
<jfs_proc:consumerRegistry rdf:resource="baz"/>
</oslc_disc:ServiceProvider>
</oslc_disc:entry>
<oslc_disc:entry>
<oslc_disc:ServiceProvider dc:title="Foo Bar Baz II">
<oslc_disc:details rdf:resource="foo2"/>
<oslc_disc:services rdf:resource="bar2"/>
<jfs_proc:consumerRegistry rdf:resource="baz2"/>
</oslc_disc:ServiceProvider>
</oslc_disc:entry>
</oslc_disc:ServiceProviderCatalog>
使用 Attean 的示例
我还没有用过很多 Attean,所以可能有更优雅的方法来做到这一点......
use strict;
use warnings;
use Attean::RDF qw(iri);
# $base is for resolving any relative URLs.
my $base = 'http://example.com/';
# Parse the data into $model
my $store = Attean->get_store('Memory')->new;
my $model = Attean::MutableQuadModel->new( store => $store );
my $data = do { local $/; <DATA> }; # slurp filehandle into string
$model->load_triples(RDFXML => iri($base), $data);
# Some namespaces for querying the data...
my $oslc = 'http://open-services.net/xmlns/discovery/1.0/';
my $dc = 'http://purl.org/dc/terms/';
# Cycle through the objects of oscl_disc:entry
for my $provider ( $model->objects(undef, iri("${oslc}entry"))->elements ) {
# Get the title. This returns a list of titles, so we call
# it in list context and get just the first result.
my ($title) = $model->objects($provider, iri("${dc}title"))->elements;
# Print it.
print "GOT: ", $title->value, "\n";
}
__DATA__
<oslc_disc:ServiceProviderCatalog
xmlns:oslc_disc="http://open-services.net/xmlns/discovery/1.0/"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:jfs_proc="https://jazz.net/xmlns/prod/jazz/process/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
rdf:about="https://localhost:9443/ccm/oslc-scm/catalog.xml"
>
<oslc_disc:entry>
<oslc_disc:ServiceProvider>
<dc:title>Foo Bar Baz</dc:title>
<oslc_disc:details rdf:resource="foo"/>
<oslc_disc:services rdf:resource="bar"/>
<jfs_proc:consumerRegistry rdf:resource="baz"/>
</oslc_disc:ServiceProvider>
</oslc_disc:entry>
<oslc_disc:entry>
<oslc_disc:ServiceProvider dc:title="Foo Bar Baz II">
<oslc_disc:details rdf:resource="foo2"/>
<oslc_disc:services rdf:resource="bar2"/>
<jfs_proc:consumerRegistry rdf:resource="baz2"/>
</oslc_disc:ServiceProvider>
</oslc_disc:entry>
</oslc_disc:ServiceProviderCatalog>