/usr/share/perl5/LaTeXML/Model/DTD.pm is in latexml 0.7.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | # /=====================================================================\ #
# | LaTeXML::Model::DTD | #
# | Extract Model information from a DTD | #
# |=====================================================================| #
# | Part of LaTeXML: | #
# | Public domain software, produced as part of work done by the | #
# | United States Government & not subject to copyright in the US. | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov> #_# | #
# | http://dlmf.nist.gov/LaTeXML/ (o o) | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Model::DTD;
use strict;
use LaTeXML::Util::Pathname;
use LaTeXML::Global;
use base qw(LaTeXML::Model::Schema);
#**********************************************************************
# NOTE: Arglist is DTD specific.
# Effectively asks for DTD submodel.
sub new {
my($class,$model,$roottag,$publicid,$systemid)=@_;
my $self = {model=>$model,roottag=>$roottag,public_id=>$publicid,system_id=>$systemid};
bless $self,$class;
$self; }
# Question: if we don't have a doctype, can we rig the queries to
# let it build a `reasonable' document?
# This is responsible for setting any DocType, and adding any
# required namespace declarations to the root element.
sub addSchemaDeclaration {
my($self,$document,$tag)=@_;
$document->getDocument->createInternalSubset($tag,$$self{public_id},$$self{system_id}); }
#**********************************************************************
# DTD Analysis
#**********************************************************************
# Uses XML::LibXML to read in the DTD. Then extracts a simplified
# model: which elements can appear within each element, ignoring
# (for now) the ordering, repeat, etc, of the elements.
# From this, and the Tag declarations of autoOpen (that an
# element can be opened automatically, if needed) we derive an implicit model.
# Thus, if we want to insert an element (or, say #PCDATA) into an
# element that doesn't allow it, we may find an implied element
# to create & insert, and insert the #PCDATA into it.
sub loadSchema {
my($self)=@_;
$$self{schema_loaded}=1;
NoteBegin("Loading DTD ".$$self{public_id}||$$self{system_id});
my $model = $$self{model};
$model->setTagProperty('#Document','model',{$$self{roottag}=>1}) if $$self{roottag};
# Parse the DTD
my $dtd = $self->readDTD;
return unless $dtd;
NoteBegin("Analyzing DTD");
# Extract all possible namespace attributes
foreach my $node ($dtd->childNodes()){
if($node->nodeType() == XML_ATTRIBUTE_DECL){
if($node->toString =~ /^<!ATTLIST\s+([a-zA-Z0-9\-\_\:]+)\s+([a-zA-Z0-9\-\_\:]+)\s+(.*)>$/){
my($tag,$attr,$extra)=($1,$2,$3);
if($attr =~ /^xmlns(:([a-zA-Z0-9-]+))?$/){
my $prefix = ($1 ? $2 : '#default');
$extra =~ /^CDATA\s+#FIXED\s+(\'|\")(.*)\1\s*$/;
my $ns = $2;
# Just record prefix, not element??
$model->registerDocumentNamespace($prefix,$ns); }}}}
# Extract all possible children for each tag.
foreach my $node ($dtd->childNodes()){
if($node->nodeType() == XML_ELEMENT_DECL){
my $decl = $node->toString();
chomp($decl);
if($decl =~ /^<!ELEMENT\s+([a-zA-Z0-9\-\_\:]+)\s+(.*)>$/){
my($tag,$content)=($1,$2);
## $$self{tagprop}{$tag}{preferred_prefix} = $1 if $tag =~ /^([^:]+):(.+)/;
$tag = $model->recodeDocumentQName($tag);
$content=~ s/[\+\*\?\,\(\)\|]/ /g;
$content=~ s/\s+/ /g; $content=~ s/^\s+//; $content=~ s/\s+$//;
if($content eq 'EMPTY'){
$model->setTagProperty($tag,'model',{}); }
else {
my @content = map($model->recodeDocumentQName($_),split(/ /,$content));
$model->setTagProperty($tag,'model',{ map(($_ => 1), @content)});
}}
else { Warn(":model Warning: got \"$decl\" from DTD");}
}
elsif($node->nodeType() == XML_ATTRIBUTE_DECL){
if($node->toString =~ /^<!ATTLIST\s+([a-zA-Z0-9-]+)\s+([a-zA-Z0-9-]+)\s+(.*)>$/){
my($tag,$attr,$extra)=($1,$2,$3);
if($attr !~ /^xmlns/){
$tag = $model->recodeDocumentQName($tag);
my $attrlist = $model->getTagProperty($tag,'attributes');
$model->setTagProperty($tag,'attributes', $attrlist={}) unless $attrlist;
if($attr =~ /:/){
$attr = $model->recodeDocumentQName($attr); }
$$attrlist{$attr}=1; }}}
}
NoteEnd("Analyzing DTD"); # Done analyzing
NoteEnd("Loading DTD ".$$self{public_id}||$$self{system_id});
}
sub readDTD {
my($self)=@_;
NoteBegin("Loading XML catalogs");
foreach my $catalog ( pathname_findall('catalog',
paths=>$STATE->lookupValue('SEARCHPATHS'),
installation_subdir=>'schema')){
NoteProgress("Loading catalog $catalog. ");
XML::LibXML->load_catalog($catalog); }
NoteEnd("Loading XML catalogs");
NoteBegin("Loading DTD for $$self{public_id} $$self{system_id}");
# NOTE: setting XML_DEBUG_CATALOG makes this Fail!!!
my $dtd = XML::LibXML::Dtd->new($$self{public_id},$$self{system_id});
if($dtd){
NoteProgress(" via catalog "); }
else { # Couldn't find dtd in catalog, try finding the file. (search path?)
my $dtdfile = pathname_find($$self{system_id},
paths=>$STATE->lookupValue('SEARCHPATHS'),
installation_subdir=>'dtd');
if($dtdfile){
NoteProgress(" from $dtdfile ");
$dtd = XML::LibXML::Dtd->new($$self{public_id},$dtdfile);
NoteProgress(" from $dtdfile ") if $dtd;
Error(":model Parsing of DTD \"$$self{public_id}\" \"$$self{system_id}\" failed")
unless $dtd;
}
else {
Error(":missing_file:$$self{system_id} Couldn't find DTD \"$$self{public_id}\" \"$$self{system_id}\" failed"); }}
$dtd; }
#**********************************************************************
1;
|