File: RootNode.pm

package info (click to toggle)
libxml-validator-schema-perl 1.10-2.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 708 kB
  • sloc: perl: 3,682; xml: 16; makefile: 2
file content (161 lines) | stat: -rw-r--r-- 4,322 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package XML::Validator::Schema::RootNode;
use strict;
use warnings;

use base 'XML::Validator::Schema::ElementNode';

use XML::Validator::Schema::Util qw(_err);
use Carp qw(croak);

=head1 NAME

XML::Validator::Schema::RootNode - the root node in a schema document

=head1 DESCRIPTION

This is an internal module used by XML::Validator::Schema to represent
the root node in an XML Schema document.  Holds references to the
libraries for the schema document and is responsible for hooking up
named types to their uses in the node tree at the end of parsing.

=cut

sub new {
    my $pkg = shift;
    my $self = $pkg->SUPER::new(@_);

    # start up with empty libraries
    $self->{type_library}      = XML::Validator::Schema::TypeLibrary->new;
    $self->{element_library}   = XML::Validator::Schema::ElementLibrary->new;
    $self->{attribute_library} = XML::Validator::Schema::AttributeLibrary->new;

    return $self;
}

# finish typing and references
sub compile {
    my $self = shift;
    my $element_library = $self->{element_library};

    # put global elements into the library (could move this to ::ElementNode)
    foreach my $d ($self->daughters) {
        if (ref($d) eq 'XML::Validator::Schema::ElementNode') {
            $element_library->add(name => $d->{name},
                                  obj  => $d);
        }
    }


    # complete all element refs first, forming a complete tree
    foreach my $element ($self->descendants) {
        $self->complete_ref($element);
    }

    # completa all element types, including their attributes
    foreach my $element ($self->descendants) {
        $self->complete_type($element);
    }

}

sub complete_ref {
    my ($self, $ref) = @_;

    # handle any unresolved attribute types
    if ($ref->{attr}) {
        $self->complete_attr_ref($_) 
          for (grep { $_->{unresolved_ref} } (@{$ref->{attr}}));
    }

    # all done unless unresolved
    return unless $ref->{unresolved_ref};

    my $name = $ref->{name};
    my ($element) = $self->{element_library}->find(name => $ref->{name});
    _err("Found unresolved reference to element '$name'")
      unless $element;



    # replace the current element
    $ref->replace_with($element->copy_at_and_under);

    return;
}

sub complete_type {
    my ($self, $element) = @_;
    my $library = $self->{type_library};

    # handle any unresolved attribute types
    if ($element->{attr}) {
        $self->complete_attr_type($_) 
          for (grep { $_->{unresolved_type} } (@{$element->{attr}}));
    }

    # all done unless unresolved
    return unless $element->{unresolved_type};

    # get type data
    my $type_name = $element->{type_name};
    my $type = $library->find(name => $type_name);

    # isn't there?
    _err("Element '<$element->{name}>' has unrecognized type '$type_name'.") 
      unless $type;


    if ($type->isa('XML::Validator::Schema::ComplexTypeNode')) {
        # can't have daughters for this to work
        _err("Element '<$element->{name}>' is using a named complexType and has sub-elements of its own.  That's not supported.")
          if $element->daughters;
    
        # replace the current element with one based on the complex node
        my $new_node = $type->copy_at_and_under;
        $new_node->name($element->{name});
        $new_node->{attr} = [ @{ $new_node->{attr} || [] }, 
                              @{ $element->{attr} || [] } ];
        $element->replace_with($new_node);


    } elsif ($type->isa('XML::Validator::Schema::SimpleType')) {
        $element->{type} = $type;

    } else {
        croak("Library returned '$type'!");
    }

    # fixed it
    delete $element->{unresolved_type};
}

sub complete_attr_type {
    my ($self, $attr) = @_;

    my $type = $self->{type_library}->find(name => $attr->{type_name});
    _err("Attribute '<$attr->{name}>' has unrecognized ".
         "type '$attr->{type_name}'.")
      unless $type;

    $attr->{type} = $type;
    delete $attr->{unresolved_type};
}

sub complete_attr_ref {
    my ($self, $ref) = @_;

    my $attr = $self->{attribute_library}->find(name => $ref->{name});
    _err("Attribute reference '$ref->{name}' not found.")
      unless $attr;
    
    # clone, keep use
    my $use = $ref->{required};
    %$ref = %$attr;
    $ref->{required} = $use;

    return;
}



1;