line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package XML::RSS::Parser; |
2
|
1
|
|
|
1
|
|
925
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
45
|
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
904
|
use XML::Elemental; |
|
1
|
|
|
|
|
8995
|
|
|
1
|
|
|
|
|
39
|
|
5
|
1
|
|
|
1
|
|
21
|
use base qw( Class::ErrorHandler ); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1058
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
418
|
use vars qw( $VERSION ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
790
|
|
8
|
|
|
|
|
|
|
$VERSION = 4.0; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
my %xpath_prefix = ( |
11
|
|
|
|
|
|
|
admin => "http://webns.net/mvcb/", |
12
|
|
|
|
|
|
|
ag => "http://purl.org/rss/1.0/modules/aggregation/", |
13
|
|
|
|
|
|
|
annotate => "http://purl.org/rss/1.0/modules/annotate/", |
14
|
|
|
|
|
|
|
atom => "http://www.w3.org/2005/Atom", |
15
|
|
|
|
|
|
|
audio => "http://media.tangent.org/rss/1.0/", |
16
|
|
|
|
|
|
|
cc => "http://web.resource.org/cc/", |
17
|
|
|
|
|
|
|
company => "http://purl.org/rss/1.0/modules/company", |
18
|
|
|
|
|
|
|
content => "http://purl.org/rss/1.0/modules/content/", |
19
|
|
|
|
|
|
|
cp => "http://my.theinfo.org/changed/1.0/rss/", |
20
|
|
|
|
|
|
|
dc => "http://purl.org/dc/elements/1.1/", |
21
|
|
|
|
|
|
|
dcterms => "http://purl.org/dc/terms/", |
22
|
|
|
|
|
|
|
email => "http://purl.org/rss/1.0/modules/email/", |
23
|
|
|
|
|
|
|
ev => "http://purl.org/rss/1.0/modules/event/", |
24
|
|
|
|
|
|
|
feedburner => "http://rssnamespace.org/feedburner/ext/1.0", |
25
|
|
|
|
|
|
|
foaf => "http://xmlns.com/foaf/0.1/", |
26
|
|
|
|
|
|
|
image => "http://purl.org/rss/1.0/modules/image/", |
27
|
|
|
|
|
|
|
itunes => "http://www.itunes.com/DTDs/Podcast-1.0.dtd", |
28
|
|
|
|
|
|
|
l => "http://purl.org/rss/1.0/modules/link/", |
29
|
|
|
|
|
|
|
openSearch => "http://a9.com/-/spec/opensearchrss/1.0/", |
30
|
|
|
|
|
|
|
rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", |
31
|
|
|
|
|
|
|
rdfs => "http://www.w3.org/2000/01/rdf-schema#", |
32
|
|
|
|
|
|
|
'ref' => "http://purl.org/rss/1.0/modules/reference/", |
33
|
|
|
|
|
|
|
reqv => "http://purl.org/rss/1.0/modules/richequiv/", |
34
|
|
|
|
|
|
|
rss091 => "http://purl.org/rss/1.0/modules/rss091#", |
35
|
|
|
|
|
|
|
search => "http://purl.org/rss/1.0/modules/search/", |
36
|
|
|
|
|
|
|
slash => "http://purl.org/rss/1.0/modules/slash/", |
37
|
|
|
|
|
|
|
ss => "http://purl.org/rss/1.0/modules/servicestatus/", |
38
|
|
|
|
|
|
|
str => "http://hacks.benhammersley.com/rss/streaming/", |
39
|
|
|
|
|
|
|
'sub' => "http://purl.org/rss/1.0/modules/subscription/", |
40
|
|
|
|
|
|
|
sy => "http://purl.org/rss/1.0/modules/syndication/", |
41
|
|
|
|
|
|
|
tapi => "http://api.technorati.com/dtd/tapi-001.xml#", |
42
|
|
|
|
|
|
|
taxo => "http://purl.org/rss/1.0/modules/taxonomy/", |
43
|
|
|
|
|
|
|
thr => "http://purl.org/rss/1.0/modules/threading/", |
44
|
|
|
|
|
|
|
trackback => "http://madskills.com/public/xml/rss/module/trackback/", |
45
|
|
|
|
|
|
|
wiki => "http://purl.org/rss/1.0/modules/wiki/", |
46
|
|
|
|
|
|
|
xhtml => "http://www.w3.org/1999/xhtml", |
47
|
|
|
|
|
|
|
xml => "http://www.w3.org/XML/1998/namespace/", |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
creativeCommons => "http://backend.userland.com/creativeCommonsRssModule" |
50
|
|
|
|
|
|
|
); |
51
|
|
|
|
|
|
|
my %xpath_ns = reverse %xpath_prefix; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub new { |
54
|
2
|
|
|
2
|
1
|
530
|
my $class = shift; |
55
|
2
|
|
|
|
|
7
|
my $self = bless {}, $class; |
56
|
2
|
|
|
|
|
10
|
my $params = { |
57
|
|
|
|
|
|
|
Document => 'XML::RSS::Parser::Feed', |
58
|
|
|
|
|
|
|
Element => 'XML::RSS::Parser::Element', |
59
|
|
|
|
|
|
|
Characters => 'XML::RSS::Parser::Characters' |
60
|
|
|
|
|
|
|
}; |
61
|
2
|
|
|
|
|
13
|
$self->{__parser} = XML::Elemental->parser($params); |
62
|
2
|
|
|
|
|
99382
|
$self; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub register_ns_prefix { |
66
|
2
|
|
|
2
|
1
|
686
|
my ($this, $prefix, $ns) = @_; |
67
|
2
|
|
|
|
|
7
|
$xpath_prefix{$prefix} = $ns; |
68
|
2
|
|
|
|
|
6
|
$xpath_ns{$ns} = $prefix; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
0
|
|
|
0
|
1
|
0
|
sub parse { _parse('parse', @_); } |
72
|
0
|
|
|
0
|
1
|
0
|
sub parse_file { _parse('parse_file', @_); } |
73
|
1
|
|
|
1
|
1
|
8
|
sub parse_string { _parse('parse_string', @_); } |
74
|
0
|
|
|
0
|
1
|
0
|
sub parse_uri { _parse('parse_uri', @_); } |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub _parse { |
77
|
1
|
|
|
1
|
|
2
|
my $meth = shift; |
78
|
1
|
|
|
|
|
2
|
my $e = shift; |
79
|
1
|
|
|
|
|
1
|
my $doc; |
80
|
1
|
|
|
|
|
3
|
eval { $doc = $e->{__parser}->$meth(@_) }; |
|
1
|
|
|
|
|
7
|
|
81
|
1
|
50
|
|
|
|
311
|
return $e->error($@) if ($@); |
82
|
1
|
|
|
|
|
5
|
$e->rss_normalize($doc); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
#--- utils |
86
|
|
|
|
|
|
|
|
87
|
24
|
|
|
24
|
1
|
64
|
sub prefix { $xpath_ns{$_[1]} } |
88
|
2
|
|
|
2
|
1
|
13
|
sub namespace { $xpath_prefix{$_[1]} } |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub ns_qualify { |
91
|
1
|
|
|
1
|
1
|
265
|
my ($this, $name, $ns) = @_; |
92
|
1
|
|
50
|
|
|
4
|
$ns ||= ''; |
93
|
1
|
|
|
|
|
4
|
"{$ns}$name"; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Since different RSS formats have slightly different tag hierarchies |
97
|
|
|
|
|
|
|
# we make some alternations after processing so bring them all into |
98
|
|
|
|
|
|
|
# line. |
99
|
|
|
|
|
|
|
sub rss_normalize { |
100
|
1
|
|
|
1
|
0
|
2
|
my $self = shift; |
101
|
1
|
|
|
|
|
2
|
my $doc = shift; |
102
|
1
|
|
|
|
|
5
|
my $ns = $doc->find_rss_namespace; |
103
|
1
|
|
|
|
|
4
|
my $channel_name = "{$ns}channel"; |
104
|
1
|
|
|
|
|
4
|
my $root = $doc->contents->[0]; |
105
|
1
|
|
|
|
|
8
|
my @new_contents; |
106
|
|
|
|
|
|
|
my $channel; |
107
|
1
|
|
|
|
|
2
|
foreach (@{$root->contents}) { |
|
1
|
|
|
|
|
4
|
|
108
|
7
|
100
|
100
|
|
|
55
|
if ($_->can('name') && ($_->name eq $channel_name)) { |
109
|
1
|
|
|
|
|
11
|
$_->parent($doc); |
110
|
1
|
|
|
|
|
4
|
$channel = $_; |
111
|
1
|
|
|
|
|
5
|
$doc->contents([$_]); |
112
|
|
|
|
|
|
|
} else { |
113
|
6
|
|
|
|
|
18
|
push(@new_contents, $_); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
} |
116
|
1
|
|
|
|
|
3
|
map { $_->parent($channel) } @new_contents; |
|
6
|
|
|
|
|
33
|
|
117
|
1
|
|
|
|
|
4
|
$channel->contents([@{$channel->contents}, @new_contents]); |
|
1
|
|
|
|
|
2
|
|
118
|
1
|
|
|
|
|
13
|
$root->parent(undef); |
119
|
1
|
|
|
|
|
5
|
$root->contents(undef); |
120
|
1
|
|
|
|
|
10
|
$doc; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
1; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
__END__ |