NAME
Data::CSel::WrapStruct - Wrap data structure into a tree of objects
suitable for use with Data::CSel
VERSION
This document describes version 0.008 of Data::CSel::WrapStruct (from
Perl distribution Data-CSel-WrapStruct), released on 2020-04-15.
SYNOPSIS
use Data::CSel qw(csel);
use Data::CSel::WrapStruct qw(wrap_struct unwrap_tree);
my $data = [
0,
1,
[2, ["two","dua"], {url=>"http://example.com/two.jpg"}, ["even","prime"]],
3,
[4, ["four","empat"], {}, ["even"]],
];
my $tree = wrap_struct($data);
my @nodes = csel(":root > * > *:nth-child(4) > *", $tree);
my @tags = map { $_->value } @nodes; # -> ("even", "prime", "even")
Scalars are wrapped using "Data::CSel::WrapStruct::Scalar" class,
scalarrefs are wrapped using "Data::CSel::WrapStruct::ScalarRef" class,
arrays are wrapped using "Data::CSel::WrapStruct::Array" class, and
hashes are wrapped using "Data::CSel::WrapStruct::Hash" class. For
convenience, when you load "Data::CSel::WrapStruct", it adds
"Data::CSel::WrapStruct" to @Data::CSel::CLASS_PREFIXES so you don't
have to specify "{class_prefixes=>["Data::CSel::WrapStruct"]}" "csel()"
option everytime.
my @hashes = map {$_->value} csel("Hash", $tree);
# -> ({url=>"http://example.com/two.jpg"}, {})
The wrapper objects provide some methods, e.g.:
my @empty_hashes = map {$_->value} csel("Hash[length=0]", $tree);
# -> ({})
my @hashes_that_have_url_key = map {$_->value} csel("Hash[has_key('url')]", $tree);
# -> ({url=>"http://example.com/two.jpg"})
my @larger_scalars = [map {$_->value} csel("Scalar[value >= 3]", $tree)]
# -> (3, 4)
See "NODE METHODS", "SCALAR NODE METHODS", "SCALARREF NODE METHODS",
"ARRAY NODE METHODS", "HASH NODE METHODS" for more details on the
provided methods.
You can replace the value of nodes using "value":
my @posint_scalar_nodes = csel("Scalar[value > 0]", $tree);
for (@posint_scalar_nodes) { $_->value( $_->value * 10 ) }
use Data::Dump;
dd unwrap_tree($data);
# => [
# 0,
# 10,
# [20, ["two","dua"], {url=>"http://example.com/two.jpg"}, ["even","prime"]],
# 30,
# [40, ["four","empat"], {}, ["even"]],
# ];
DESCRIPTION
This module provides "wrap_struct()" which creates a tree of objects
from a generic data structure. You can then perform node selection using
Data::CSel's "csel()".
You can retrieve the original value of data items by calling "value()"
method on the tree nodes.
NODE METHODS
parent
children
value
Usage:
my $val = $node->value; # get node value
$node->value(1); # set node value
Get or set node value.
Note that when setting node value, the new node value is not
automatically wrapped for you. If you want to set new node value and
expect to select it or part of it again with "csel()", you will have to
wrap the new value first with "wrap_struct".
remove
Usage:
$node->remove;
Remove node from parent.
SCALAR NODE METHODS
In addition to methods listed in "NODE METHODS", Scalar nodes also have
the following methods.
SCALARREF NODE METHODS
In addition to methods listed in "NODE METHODS", ScalarRef nodes also
have the following methods.
ARRAY NODE METHODS
In addition to methods listed in "NODE METHODS", Array nodes also have
the following methods.
length
Get array length. Can be used to select an array based on its length,
e.g.:
@nodes = csel('Array[length > 0]');
HASH NODE METHODS
In addition to methods listed in "NODE METHODS", Hash nodes also have
the following methods.
length
Get the number of keys. Can be used to select a hash based on its number
of keys, e.g.:
@nodes = csel('Hash[length > 0]');
has_key
Usage:
my $bool = $node->has_key("foo");
Check whether hash has a certain key. Can be used to select a hash,
e.g.:
@nodes = csel('Hash[has_key("foo")]');
key
Usage:
my $key_val = $node->key("foo");
Get a hash key's value. Can be used to select a hash based on the value
of one of its keys, e.g.:
@nodes = csel('Hash[key("name") = "lisa"]');
FUNCTIONS
None exported by default, but exportable.
wrap_struct
Usage:
my $tree = wrap_struct($data);
Wrap a data structure into a tree of objects.
Currently cannot handle recursive structure.
unwrap_tree
Usage:
my $data = unwrap_tree($wrapped_data);
Unwrap a tree produced by "wrap_tree" back into unwrapped data
structure.
FAQ
Changing the node value doesn't work!
my $data = [0, 1, 2];
my @nodes = csel("Scalar[value > 0]", wrap_struct($data));
for (@nodes) { $_->[0] = "x" }
use Data::Dump;
dd $data;
still prints "[0,1,2]" instead of "[0,'x','x']". Why?
To set node value, you have to use the "value()" node method with an
argument:
...
for (@nodes) { $->value("x") }
...
will then print the expected "[0,'x','x']".
This module is slow!
If you intend to select a data structure with thousands of nodes or
more, you're probably better off using other approach, for example
Data::Walk::More. Data::Walk::More provides containers for the nodes
you're traversing. For example, the CSel expression
"Hash[has_keys("foo")] > Array > Scalar[value > 0]" can be written as:
walk sub {
my $ref = ref $_;
return if ref $_; # ... Scalar
return if $_ <= 0; # ... [value > 0]
return unless ref $Data::Walk::More::containers[-1] eq 'ARRAY'; # ... Array
return unless ref $Data::Walk::More::containers[-2] eq 'HASH'; # ... Hash
return unless exists $Data::Walk::More::containers[-2]{foo}; # ... [has_keys("foo")]
push @matches, $_;
}, $data;
HOMEPAGE
Please visit the project's homepage at
<https://metacpan.org/release/Data-CSel-WrapStruct>.
SOURCE
Source repository is at
<https://github.com/perlancar/perl-Data-CSel-WrapStruct>.
BUGS
Please report any bugs or feature requests on the bugtracker website
<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-CSel-WrapStruct>
When submitting a bug or request, please include a test-file or a patch
to an existing test-file that illustrates the bug or desired feature.
SEE ALSO
Data::CSel
AUTHOR
perlancar <perlancar@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2020, 2016 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.