XML-Compile
view release on metacpan or search on metacpan
lib/XML/Compile/Translate/Writer.pm view on Meta::CPAN
};
$mode eq 'MINIMAL'
and return sub
{ my $value = $do->(@_);
return () if defined $value && $value eq $default;
$_[0]->createAttribute($tag, $value);
};
error __x"illegal default_values mode `{mode}'", mode => $mode;
}
sub makeAttributeFixed
{ my ($self, $path, $ns, $tag, $label, $do, $fixed) = @_;
$fixed = $fixed->value if ref $fixed;
sub { my ($doc, $value) = @_;
defined $value or return ();
$value eq $fixed
or error __x"value of attribute `{tag}' is fixed to `{fixed}', not `{got}' at {path}"
, tag => $tag, got => $value, fixed => $fixed, path => $path;
$doc->createAttribute($tag, $fixed);
};
}
# any
sub _split_any_list($$$)
{ my ($path, $type, $v) = @_;
my @nodes = ref $v eq 'ARRAY' ? @$v : defined $v ? $v : return ([], []);
my (@attrs, @elems);
foreach my $node (@nodes)
{ UNIVERSAL::isa($node, 'XML::LibXML::Node')
or error __x"elements for 'any' are XML::LibXML nodes, not {string} at {path}"
, string => $node, path => $path;
if($node->isa('XML::LibXML::Attr'))
{ push @attrs, $node;
next;
}
if($node->isa('XML::LibXML::Element'))
{ push @elems, $node;
next;
}
error __x"an XML::LibXML::Element or ::Attr is expected as 'any' or 'anyAttribute value with {type}, but a {kind} was found at {path}"
, type => $type, kind => ref $node, path => $path;
}
return (\@attrs, \@elems);
}
sub makeAnyAttribute
{ my ($self, $path, $handler, $yes, $no, $process) = @_;
my %yes = map +($_ => 1), @{$yes || []};
my %no = map +($_ => 1), @{$no || []};
my $prefs = $self->{prefixes};
weaken $self;
bless
sub { my ($doc, $values) = @_;
my @res;
foreach my $label (sort keys %$values)
{ my ($type, $ns, $local);
if(substr($label, 0, 1) eq '{')
{ ($ns, $local) = unpack_type $label;
$type = $label;
}
elsif(index($label, ':') >= 0)
{ (my $prefix, $local) = split ':', $label, 2;
my $match = first {$_->{prefix} eq $prefix} values %$prefs;
my $ns = $match ? $match->{uri} : undef;
$type = pack_type $ns, $local;
}
else {next} # not fully qualified, not an 'any'
$yes{$ns} or next if keys %yes;
$no{$ns} and next if keys %no;
my $value = delete $values->{$label} or next;
my ($attrs, $elems) = _split_any_list $path, $type, $value;
$values->{$type} = $elems if @$elems;
@$attrs or next;
foreach my $node (@$attrs)
{ my $nodetype = type_of_node $node;
next if $nodetype eq $type;
error __x"provided 'anyAttribute' node has type {type}, but labeled with {other} at {path}"
, type => $nodetype, other => $type, path => $path
}
push @res, @$attrs;
}
@res;
}, 'ANY';
}
sub makeAnyElement
{ my ($self, $path, $handler, $yes, $no, $process, $min, $max) = @_;
my %yes = map +($_ => 1), @{$yes || []};
my %no = map +($_ => 1), @{$no || []};
my $prefs = $self->{prefixes};
$handler ||= 'SKIP_ALL';
weaken $self;
bless
sub { my ($doc, $values) = @_;
my @res;
foreach my $label (sort keys %$values)
{ my ($type, $ns, $local);
if(substr($label, 0, 1) eq '{')
{ ($ns, $local) = unpack_type $label;
$type = $label;
}
elsif(index($label, ':') >= 0)
{ (my $prefix, $local) = split ':', $label, 2;
my $match = first {$_->{prefix} eq $prefix} values %$prefs;
$ns = $match ? $match->{uri} : undef;
$type = pack_type $ns, $local;
}
else {next} # not fully qualified, not an 'any'
$yes{$ns} or next if keys %yes;
$no{$ns} and next if keys %no;
my $value = delete $values->{$label} or next;
my ($attrs, $elems) = _split_any_list $path, $type, $value;
$values->{$type} = $attrs if @$attrs;
@$elems or next;
foreach my $node (@$elems)
{ my $nodens = $node->namespaceURI;
defined $nodens or next; # see README.todo work-around
my $nodetype = type_of_node $node;
next if $nodetype eq $type;
error __x"provided 'any' element node has type {type}, but labeled with {other} at {path}"
, type => $nodetype, other => $type, path => $path
}
push @res, @$elems;
$max eq 'unbounded' || @res <= $max
or error __x"too many 'any' elements after consuming {count} nodes of {type}, max {max} at {path}"
, count => scalar @$elems, type => $type
, max => $max, path => $path;
}
@res >= $min
or error __x"too few 'any' elements, got {count} for minimum {min} at {path}"
, count => scalar @res, min => $min, path => $path;
@res ? @res : undef; # empty, then "0 but true"
}, 'ANY';
}
# xsi:type handling
sub makeXsiTypeSwitch($$$$)
{ my ($self, $where, $elem, $default_type, $types) = @_;
my $xsi = $self->_registerNSprefix(xsi => SCHEMA2001i, 1) . ':type';
my %types;
foreach my $type (sort keys %$types)
{ my ($ns, $local) = unpack_type $type;
my $tag = $self->makeTagQualified($where, undef, $local, $ns);
# register code under both prefixed and full type name
$types{$self->prefixed($type)} = $types{$type} = [$tag,$types->{$type}];
}
sub {
my ($doc, $values) = @_;
ref $values eq 'HASH' && $values->{XSI_TYPE}
or return $types{$default_type}[1]->(@_);
my %v = %$values;
( run in 1.103 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )