Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more careful translating ReLaxNG wildcard attributes #2160

Merged
merged 1 commit into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions lib/LaTeXML/Common/Model.pm
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ sub setSchemaClass {
# NOTE: These are public, but perhaps should be passed
# to submodel, in case it can evolve to more precision?
# However, it would need more context to do that.
# NOTE: That * matches any NON-namespaced name; *:* matches any namespaced name

# Can an element with (qualified name) $tag contain a $childtag element?
sub canContain {
Expand Down Expand Up @@ -396,13 +397,15 @@ sub canContain {
: ($$model{"!$childtag"} ? 0
: ($$model{"$chns:*"} ? 1
: ($$model{"!$chns:*"} ? 0
: ($$model{'*:*'} ? 1
: 0))))); }
: ($$model{'!*:*'} ? 0
: ($$model{'*:*'} ? 1
: 0)))))); }
else {
return ($$model{$childtag} ? 1
: ($$model{"!$childtag"} ? 0
: ($$model{'*:*'} ? 1
: 0))); } }
: ($$model{'!*'} ? 0
: ($$model{'*'} ? 1
: 0)))); } }

# NOTE: Currently the Document class already allows ANY namespaced attributes!
# (which is very unmodular, although it does have to arrange for namespace declarations)
Expand Down Expand Up @@ -432,13 +435,15 @@ sub canHaveAttribute {
: ($$attr{"!$attrib"} ? 0
: ($$attr{"$attrns:*"} ? 1
: ($$attr{"!$attrns:*"} ? 0
: ($$attr{'*:*'} ? 1
: ($$attr{'!*:*'} ? 0
: ($$attr{'!*:*'} ? 0
: ($$attr{'*:*'} ? 1
: 0)))))); }
else {
return ($$attr{$attrib} ? 1
: ($$attr{"!$attrib"} ? 0
: 0)); } }
: ($$attr{'!*'} ? 0
: ($$attr{'*'} ? 1
: 0)))); } }

sub isInSchemaClass {
my ($self, $classname, $tag) = @_;
Expand Down
21 changes: 16 additions & 5 deletions lib/LaTeXML/Common/Model/RelaxNG.pm
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ sub loadSchema {
next; }
my @body = @{ $$self{elements}{$tag} };
my ($content, $attributes) = $self->extractContent($tag, @body);
$$self{model}->addTagContent($tag, sort keys %$content);
$$self{model}->addTagAttribute($tag, sort keys %$attributes); }
$$self{model}->addTagContent($tag, filterNames($content));
$$self{model}->addTagAttribute($tag, filterNames($attributes)); }
# Extract definitions of symbols that define Schema Classes, too
foreach my $symbol (sort keys %{ $$self{defs} }) {
if ($symbol =~ /^grammar\d+:(.+?)\.class$/) {
Expand All @@ -96,6 +96,17 @@ sub loadSchema {
ProgressSpindown("Loading RelaxNG $$self{name}");
return; }

# collapse redundancies like having both *:* and !*:*
sub filterNames {
my ($hash) = @_;
my %filtered = ();
foreach my $name (keys %$hash) {
if (($name ne '!*') # !* can be omitted; only cancels *
&& ((($name =~ /^!(.*)$/) && !(defined $$hash{$1})) # Negated name, but name not present?
|| (!defined $$hash{ '!' . $name }))) { # Or negation of name not present
$filtered{$name} = 1; } }
return sort keys %filtered; }

# Return two hashrefs for content & attributes
sub extractContent {
my ($self, $tag, @body) = @_;
Expand Down Expand Up @@ -343,12 +354,12 @@ sub scanNameClass {
my @exceptions = (); # Check for exceptions!
if (my @children = getElements($node)) {
@exceptions = map { $self->scanNameClass($_, $forattr, $ns) } @children; }
return ('*:*', @exceptions); }
return ('*', '*:*', @exceptions); } # anyName can be namespaced or not
elsif ($relaxop eq 'rng:nsName') {
my @exceptions = (); # Check for exceptions!
my @exceptions = (); # Check for exceptions!
if (my @children = getElements($node)) {
@exceptions = map { $self->scanNameClass($_, $forattr, $ns) } @children; }
return ($$self{model}->encodeQName($node->getAttribute('ns') || $ns, '*'), @exceptions); }
return ($$self{model}->encodeQName($node->getAttribute('ns') // $ns, '*'), @exceptions); }
elsif ($relaxop eq 'rng:choice') {
my %names = ();
foreach my $choice ($node->childNodes) {
Expand Down
Loading
Loading