| CSS-Selector-Parser documentation | Contained in the CSS-Selector-Parser distribution. |
CSS::Selector::Parser - parse CSS selectors to Perl data structures
version 0.002
use CSS::Selector::Parser 'parse_selector';
my @rules = parse_selector('#foo .bar, baz:quux');
# [ { id => 'foo' }, { class => 'bar', combinator => ' ' } ]
# [ { element => 'baz', pseudo => { quux => undef } ]
This module parses CSS selectors and gives back a series of Perl data structures corresponding to the selectors.
CSS::Selector::Parser uses Sub::Exporter. See its documentation for various ways to customize exporting.
my @rules = parse_selector($selector);
CSS selectors are mapped to Perl data structures. Each set of selectors is returned as an arrayref of hashrefs (see SYNOPSIS for an example).
The hashrefs have:
foo in foo#bar.baz.
bar in foo#bar.baz. Note: NOT [id="..."].
baz in foo#bar.baz. Note: NOT [class="..."].
A hashref of attribute selectors, each of which has a hashref of operators and values:
parse_selector('[foo="bar"]')
# [ { attr => { foo => { '=' => 'bar' } } } ]
Attribute selectors can also test for presence:
parse_selector('[foo]')
# [ { attr => { foo => undef } } ]
A hashref of pseudo-classes and their contents, if present:
parse_selector(':active:nth(2)')
# [ { pseudo => { active => undef, nth => 2 } } ]
All hashrefs after the first will have this. One of <[ +]>>. See
SYNOPSIS for an example.
HTML::Selector::XPath, from which I stole code
Hans Dieter Pearcey <hdp@cpan.org>
This software is copyright (c) 2010 by Hans Dieter Pearcey <hdp@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as perl itself.
| CSS-Selector-Parser documentation | Contained in the CSS-Selector-Parser distribution. |
package CSS::Selector::Parser; our $VERSION = '0.002'; # ABSTRACT: parse CSS selectors to Perl data structures use strict; use warnings; use Sub::Exporter -setup => { exports => [ qw(parse_selector) ], }; my $re_name = qr/[-\w]+/; # taken from HTML::Selector::XPath my $re_attr_value = qr/^\[\s*([^~\|=\s]+)\s*([~\|]?=)\s*"([^"]+)"\s*\]/; my $re_attr_exist = qr/^\[([^\]]*)\]/; my $re_pseudo = qr/^:([()a-z0-9_-]+)/; my $re_combinator = qr/^(\s*[>+\s])/; my $re_comma = qr/^\s*,/; sub parse_selector { local $_ = shift; my @rules; s/\s+$//; RULE: { #warn "RULE: $_\n"; my $combinator; my @selector; SIMPLE: { s/^\s+//; #warn "SIMPLE: $_\n"; my ($element, $id, $class, %attr, %pseudo); $element = $1 if s/^($re_name|\*)//; SUB: { $id = $1, redo SUB if s/^\#($re_name)//; $class = $1, redo SUB if s/^\.($re_name)//; if (s/$re_attr_value//) { $attr{$1}{$2} = $3; redo SUB; } if (s/$re_attr_exist//) { $attr{$1} = undef unless exists $attr{$1}; redo SUB; } # XXX grab :not first if (s/$re_pseudo//) { my $p = $1; if ($p =~ s/\((.+)\)$//) { $pseudo{$p} = $1; } else { $pseudo{$p} = undef; } redo SUB; } } my $simple = { element => $element, id => $id, class => $class, attr => \%attr, pseudo => \%pseudo, combinator => $combinator, }; for (keys %$simple) { delete $simple->{$_} unless defined $simple->{$_}; } for (qw(attr pseudo)) { delete $simple->{$_} unless %{$simple->{$_}}; } #warn Dumper($simple); push @selector, $simple; $combinator = undef; if (s/$re_combinator//) { $combinator = $1; redo SIMPLE; } push @rules, \@selector; redo RULE if s/$re_comma//; last RULE unless $_; die "fell off the end of parsing: $_\n"; } } return @rules; } 1;
__END__