File Coverage

/root/.cpan/build/XML-BindData-0.3.2-0/blib/lib/XML/BindData.pm
Criterion Covered Total %
statement 63 64 98.4
branch 27 30 90.0
condition 12 15 80.0
subroutine 7 7 100.0
pod 1 2 50.0
total 110 118 93.2


line stmt bran cond sub pod time code
1 2     2   1508 use strict;
  2         4  
  2         59  
2 2     2   11 use warnings;
  2         2  
  2         92  
3              
4             package XML::BindData;
5             $XML::BindData::VERSION = '0.3.2';
6 2     2   1414 use XML::LibXML;
  2         113501  
  2         12  
7              
8             sub bind {
9 26     26 1 15804 my ($class, $xml_string, $data) = @_;
10              
11 26         87 my $xml = XML::LibXML->load_xml(string => $xml_string);
12 26         6265 parse_node($xml->documentElement, $data);
13              
14 26         321 return $xml->toStringC14N(1);
15             }
16              
17             sub parse_node {
18 67     67 0 133 my ($node, $context) = @_;
19              
20 67 100       119 if (my $if_key = _strip_attr($node, 'tmpl-if')) {
21 8         33 my $unless = $if_key =~ s/^!//;
22 8         18 my $val = _get($context, $if_key);
23 8 100 100     43 if ( (!$unless && ! defined $val)
      100        
      100        
24             || ( $unless && defined $val)) {
25 3         12 $node->unbindNode;
26             }
27             }
28              
29 67 100       809 if (my $each_key = _strip_attr($node, 'tmpl-each')) {
30 10         38 my $parent = $node->parentNode;
31              
32 10         24 my $to_add = _get($context, $each_key);
33 10 50 33     53 if (!$to_add || ref $to_add ne 'ARRAY') {
34 0         0 $to_add = [];
35             }
36              
37 10         22 foreach my $subcontext ( reverse @$to_add ) {
38 21         316 my $new = $node->cloneNode(1); # deep clone
39 21         58 parse_node($new, $subcontext);
40 21         165 $parent->insertAfter( $new, $node );
41             }
42 10         207 $node->unbindNode;
43 10         28 return;
44             }
45              
46 57 100       659 if (my $binding = _strip_attr($node, 'tmpl-bind')) {
47 24         52 my $val = _get($context, $binding);
48              
49 24         46 my $default = _strip_attr($node, 'tmpl-default');
50              
51 24 100       277 unless (defined $val) {
52 2 100       5 $val = defined $default ? $default : '';
53             }
54              
55 24         89 $node->appendTextNode($val);
56             }
57              
58 57 100       404 if (my $attr_map = _strip_attr($node, 'tmpl-attr-map')) {
59 7         62 my @attributes = map { [ split qr/:/ ] } split qr/,/, $attr_map;
  17         104  
60              
61 7         19 foreach (@attributes) {
62 17         99 my $value = _get( $context, $_->[1] );
63 17 100       59 $node->setAttribute( $_->[0], $value ) if defined $value;
64             }
65             }
66              
67 57 100       572 if ( my $attr_defaults = _strip_attr( $node, 'tmpl-attr-defaults' ) ) {
68             my @attributes
69             = map {
70 4         39 [ map { s/\\([:,])/$1/g; $_ } # remove backslash escaping
  10         54  
  20         37  
  20         53  
71             split qr/(?
72             ]
73             }
74             split qr/(?
75             $attr_defaults;
76              
77 4         16 foreach (@attributes) {
78 10         42 my $value = $node->getAttribute( $_->[0] );
79 10 100 66     112 $node->setAttribute( $_->[0], $_->[1] )
80             if ! defined $value || $value eq '';
81             }
82             }
83              
84             my @children = grep {
85 57         623 $_->nodeType eq XML_ELEMENT_NODE
  49         483  
86             } $node->childNodes;
87 57         264 parse_node($_, $context) foreach @children;
88             }
89              
90             sub _get {
91 58     58   105 my ($context, $key) = @_;
92              
93 58 50       125 return '' if !defined $key;
94              
95 58 100       133 return $context if $key eq 'this';
96              
97 42         253 my @parts = split qr/\./, $key;
98 42         108 foreach (@parts) {
99 44         144 $context = $context->{$_};
100             }
101 42         85 return $context;
102             }
103              
104             sub _strip_attr {
105 329     329   551 my ($node, $attr_name) = @_;
106              
107 329 50       662 if (my $attributes = $node->attributes) {
108 329 100       5309 if (my $attr = $attributes->removeNamedItem($attr_name)) {
109 55         1717 return $attr->nodeValue;
110             }
111             }
112             }
113              
114             1;
115              
116             __END__