/[suikacvs]/messaging/manakai/lib/Message/Markup/XML/Error.pm
Suika

Contents of /messaging/manakai/lib/Message/Markup/XML/Error.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations) (download)
Sat Jul 5 07:25:50 2003 UTC (23 years, 1 month ago) by wakaba
Branch: MAIN
Changes since 1.5: +157 -9 lines
XML Catalog support

1 wakaba 1.1
2     =head1 NAME
3    
4     SuikaWiki::Markup::XML::Error --- SuikaWiki XML: Error handling module for SuikaWiki::Markup::XML::*
5    
6     =head1 DESCRIPTION
7    
8 wakaba 1.3 This module provides the common error and/or warning handling interface
9     for the SuikaWiki::Markup::XML::* modules. With this module, proper error
10     recovering and proper message outputing (eg. output as HTML element,
11     localized message, etc.) is easily implementable.
12    
13 wakaba 1.1 This module is part of SuikaWiki XML support.
14    
15     =cut
16    
17     package SuikaWiki::Markup::XML::Error;
18     use strict;
19 wakaba 1.6 our $VERSION = do{my @r=(q$Revision: 1.5 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
20     our %NS;
21     *NS = \%SuikaWiki::Markup::XML::NS;
22 wakaba 1.3
23     ## Prefixes:
24     ## - 'SYNTAX_': don't match with XML 1.0 EBNF rules
25     ## - 'WFC_': violation of well-formedness constraint (fatal error)
26     ## - 'VC_': violation of validity constraint (error)
27     ## - 'NC_': violation of namespace constraint (error)
28     ## - 'NS_SYNTAX_': don't match with XML Namespace 1.0 EBNF rules (error)
29     ## - 'FATAL_ERR_': fatal error specified by XML 1.0 spec
30     ## - 'ERR_': error specified by XML 1.0 spec
31     ## - 'WARN_': don't fullfil XML spec's or implementor's recommendation
32    
33     ## Error levels:
34     ## - wfc: well-formedness (including syntax error)
35     ## - vc: validity
36     ## - nswfc: namespace well-formedness
37     ## - nsvc: namespace validity
38     ## - fatal: fatal error
39     ## - warn: warning
40 wakaba 1.1
41     my %_Error = (
42 wakaba 1.3 ## Forward compatibility error
43     SYNTAX_UNSUPPORTED_XML_VERSION => {
44     description => 'Unsupported XML version (%s)',
45     level => 'wfc',
46     },
47 wakaba 1.1 ## Syntax errors
48 wakaba 1.5 SYNTAX_ATTR_LITERAL_NOT_FOUND => {
49     description => 'Attribute value literal of the attribute (name = %s) is expected',
50     level => 'wfc',
51     },
52     SYNTAX_ATTR_NAME_OMITTED => {
53     description => 'Attribute name corresponding to the value (%s) must be specified in XML',
54     level => 'wfc',
55     },
56 wakaba 1.1 SYNTAX_DATA_OUT_OF_ROOT_ELEMENT => {
57     description => 'Invalid data or markup out of root element',
58     level => 'wfc',
59     },
60 wakaba 1.4 SYNTAX_DOCTYPE_NAME_NOT_FOUND => {
61     description => 'Document type name must be specified in the document type declaration',
62     level => 'wfc',
63     },
64     SYNTAX_DOCTYPE_PID_LITERAL_NOT_FOUND => {
65     description => 'Minimum literal for the public identifier must follow the keyword PUBLIC',
66     level => 'wfc',
67     },
68     SYNTAX_DOCTYPE_SYSID_LITERAL_NOT_FOUND => {
69     description => 'Literal of the system identifier must follow the keyword SYSTEM or the minimum literal of the public identifier in XML',
70     level => 'wfc',
71     },
72 wakaba 1.1 SYNTAX_END_OF_MARKUP_NOT_FOUND => {
73     description => sub {
74     my ($o, $err) = @_;
75     my $o_start = $err->{t}->flag ('p_o_start');
76     my $r = $err->{t}->qname;
77     $r = sprintf 'line %d, position %d%s', $o_start->{line},
78     $o_start->{pos}, ($r ? '; '.$r : '') if ref $o_start;
79     $r ? $r = '; '.$r : 0;
80     $err->{t} = $err->{t}->node_type;
81     'Markup is not closed (%s'.$r.')';
82     },
83     level => 'wfc',
84     },
85     SYNTAX_END_TAG_NOT_FOUND => {
86     description => sub {
87     my ($o, $err) = @_;
88     my $o_start = $err->{t}->flag ('p_o_start');
89     my $r = '';
90     $r = sprintf 'line %d, position %d%s', $o_start->{line},
91     $o_start->{pos}, ($r ? '; '.$r : '') if ref $o_start;
92     $r ? $r = '; '.$r : 0;
93     $err->{t} = $err->{t}->qname;
94     'End tag of element (type = %s'.$r.') not found';
95     },
96     level => 'wfc',
97     },
98     SYNTAX_INVALID => {
99     description => 'This type of markup (%s) cannot appear here',
100     level => 'wfc',
101     },
102     SYNTAX_INVALID_CHAR => {
103     description => 'Invalid character (%s) at this context',
104     level => 'wfc',
105     },
106     SYNTAX_INVALID_DOCTYPE_POSITION => {
107     description => 'DOCTYPE declaration must be between xml declaration and the root element',
108     level => 'wfc',
109     },
110     SYNTAX_INVALID_KEYWORD => {
111     description => 'Invalid keyword (%s) at this context',
112     level => 'wfc',
113     },
114     SYNTAX_INVALID_LITERAL => {
115     description => 'Literal cannot be here ("%s")',
116     level => 'wfc',
117     },
118     SYNTAX_INVALID_MD => {
119     description => 'Invalid syntax of markup declaration',
120     level => 'wfc',
121     },
122     SYNTAX_INVALID_POSITION => {
123     description => sub {
124     my ($o) = shift;
125     'This type of markup (%s) cannot be used '.({
126     document_entity => 'out of DTD',
127     dtd_internal_subset => 'in the internal subset of DTD',
128     dtd_external_subset => 'in the external subset of DTD',
129     external_parsed_entity => 'in the external parsed entity',
130     general_external_parsed_entity => 'in the general external parsed entity',
131     }->{$o->{entity_type}||'document_entity'}||'in '.$o->{entity_type})},
132     level => 'wfc',
133     },
134 wakaba 1.3 SYNTAX_INVALID_PUBID => {
135     description => 'This public identifier contains at least one invalid character (%s)',
136     level => 'wfc',
137     },
138 wakaba 1.1 SYNTAX_LEGAL_CHARACTER => {
139     description => sub {
140     my $r = sprintf 'The character U-%08X is not a legal XML Char',
141     $_[1]->{t};
142     $_[1]->{t} = undef;
143     $r;
144     },
145     level => 'wfc',
146     },
147     SYNTAX_MD_NAME_NOT_FOUND => {
148     description => 'Name is required by this type of declaration',
149     level => 'wfc',
150     },
151     SYNTAX_MD_SYSID_NOT_FOUND => {
152     description => 'System identifier is required by this type of declaration',
153     level => 'wfc',
154     },
155 wakaba 1.4 SYNTAX_MS_IN_INTERNAL_SUBSET => {
156     description => 'Marked section cannot be used in the internal subset of the DTD in XML',
157     level => 'wfc',
158     },
159     SYNTAX_MS_INVALID_STATUS_STRING => {
160     description => 'Invalid string in the status keyword list',
161     level => 'wfc',
162     },
163     SYNTAX_MS_MULTIPLE_STATUS => {
164     description => 'Multiple status keyword (%s) cannot be used',
165     level => 'wfc',
166     },
167     SYNTAX_MS_NO_STATUS_KEYWORD => {
168     description => 'No status keyword found',
169     level => 'wfc',
170     },
171     SYNTAX_MS_NON_XML_STATUS => {
172     description => 'This status keyword (%s) cannot be used in XML',
173     level => 'wfc',
174     },
175     SYNTAX_MS_UNKNOWN_STATUS => {
176     description => 'Unknown status keyword (%s) is used',
177     level => 'wfc',
178     },
179 wakaba 1.1 SYNTAX_PE_NDATA => {
180     description => 'Parameter entity must be a parsed entity',
181     level => 'wfc',
182     },
183 wakaba 1.4 SYNTAX_ROOT_ELEMENT_NOT_FOUND => {
184     description => 'There is no root element (type = %s) in this document entity',
185     level => 'wfc',
186     },
187 wakaba 1.5 SYNTAX_TAG_NOT_CLOSED => {
188     description => 'Tag must be closed in XML',
189     level => 'wfc',
190     },
191 wakaba 1.1 SYNTAX_XML_DECLARE => {
192     description => 'Syntax of XML (or text) declaration is invalid',
193     level => 'wfc',
194     },
195     SYNTAX_XML_DECLARE_NO_ATTR => {
196 wakaba 1.3 description => 'XML (or text) declaration has no (valid) pseudo attribute',
197     level => 'wfc',
198     },
199     SYNTAX_XML_DECLARE_NO_ENCODING_ATTR => {
200     description => q(Text declaration must have 'encoding' pseudo attribute),
201     level => 'wfc',
202     },
203     SYNTAX_XML_DECLARE_NO_VERSION_ATTR => {
204     description => q(XML declaration must have 'version' pseudo attribute),
205 wakaba 1.1 level => 'wfc',
206     },
207     SYNTAX_XML_DECLARE_POSITION => {
208     description => 'XML declaration must be at the top of the entity',
209     level => 'wfc',
210     },
211 wakaba 1.3 SYNTAX_XML_DECLARE_STANDALONE_ATTR => {
212     description => q(Text declaration cannot have 'standalone' pseudo attribute),
213     level => 'wfc',
214     },
215 wakaba 1.1 ## Well-formedness error
216     WFC_ELEMENT_TYPE_MATCH => {
217     description => 'End tag (type = %s) does not match with start tag (type = %s)',
218     level => 'wfc',
219     },
220     WFC_ENTITY_DECLARED => {
221     description => 'Entity (%s) must be declared before it is referred',
222     level => 'wfc',
223     },
224     WFC_LEGAL_CHARACTER => {
225     description => sub {
226     my $r = sprintf 'The character referred (U-%08X) is not a legal XML Char',
227     $_[1]->{t};
228     $_[1]->{t} = undef;
229     $r;
230     },
231     level => 'wfc',
232     },
233     WFC_NO_EXTERNAL_ENTITY_REFERENCE => {
234     description => 'Attribute value must not contain reference to an external entity',
235     level => 'wfc',
236     },
237     WFC_NO_LE_IN_ATTRIBUTE_VALUE => {
238     description => 'Attribute value must not contain a less-than sign (<)',
239     level => 'wfc',
240     },
241     WFC_NO_RECURSION => {
242     description => 'Parsed entity (%s) must not contain a recursive reference to itself',
243     level => 'wfc',
244     },
245     WFC_NO_LT_IN_ATTRIBUTE_VALUE => {
246     description => 'Replacement text of entity reference in an attribute value literal cannot contain LESS-THAN SIGN (<) itself',
247     level => 'wfc',
248     },
249 wakaba 1.3 WFC_PARSED_ENTITY => {
250     description => 'Entity reference (%s) must not refer non-parsed entity',
251     level => 'wfc',
252     },
253 wakaba 1.1 WFC_PE_IN_INTERNAL_SUBSET => {
254     description => 'Parameter entity (%s) cannot be referred in markup declaration in internal subset of DTD',
255     level => 'wfc',
256     },
257     WFC_UNIQUE_ATT_SPEC => {
258     description => 'Dupulicate attribute specification',
259     level => 'wfc',
260     },
261 wakaba 1.3 FATAL_ERR_DECODE_IMPL_ERR => {
262     description => 'Decode error (%s)',
263     level => 'fatal',
264     },
265     FATAL_ERR_PREDEFINED_ENTITY => {
266 wakaba 1.4 description => 'Predefined entity (%s := %s) must be declared as of the XML specification defined',
267 wakaba 1.3 level => 'fatal',
268 wakaba 1.2 },
269 wakaba 1.1 ## Validity error
270     VC_ENTITY_DECLARED => {
271     description => 'Entity %s should (or must to be valid) be declared before it is referred',
272     level => 'vc',
273     },
274     VC_NOTATION_DECLARED => {
275     description => 'Notation %s should (or must to be valid) be declared',
276     level => 'vc',
277     },
278 wakaba 1.4 VC_ROOT_ELEMENT_TYPE => {
279     description => 'Document type name (%s) and element type name of the root element (%s) should (or must to be valid) match',
280     level => 'vc',
281     },
282 wakaba 1.1 VC_UNIQUE_NOTATION_NAME => {
283     description => 'Notation %s is already declared',
284     level => 'warn',
285     },
286     ## Namespace well-formedness error
287 wakaba 1.5 NS_SYNTAX_LNAME_IS_NCNAME => {
288     description => 'Character just after the colon (:) in QName (%s) must be one of NameStartChar in namespaced XML document',
289     level => 'nswfc',
290     },
291 wakaba 1.1 NC_PREFIX_NOT_DEFINED => {
292     description => 'Undeclared namespace prefix (%s) is used',
293     level => 'nswfc',
294     },
295     NS_SYNTAX_NAME_IS_NCNAME => {
296 wakaba 1.5 description => 'Name with colon (%s) cannot be used here in namespaced XML document',
297 wakaba 1.1 level => 'nswfc',
298     },
299 wakaba 1.5 NS_SYNTAX_NAME_IS_QNAME => {
300     description => 'Name with colon (%s) must match with QName in namespaced XML document',
301     level => 'nswfc',
302     },
303     NC_UNIQUE_ATT_SPEC => {
304     description => 'Dupulicate attribute specification (%s == <%s>:%s)',
305     level => 'wfc',
306     },
307 wakaba 1.1 ## Namespace validity error
308 wakaba 1.4 ## XML (non-fatal) error
309 wakaba 1.3 ERR_EXT_ENTITY_NOT_FOUND => {
310     description => 'External entity (%s == <%s>) cannot be retrived (%s)',
311     level => 'vc',
312     },
313 wakaba 1.4 ERR_XML_NDATA_REF_IN_ENTITY_VALUE => {
314     description => 'Unparsed entity (%s) cannot be referred in EntityValue',
315     level => 'warn', ## Was fatal error but refined by SE Errata
316     },
317     ERR_XML_SYSID_HAS_FRAGMENT => {
318 wakaba 1.3 description => 'URI Reference converted from system identifier should not have the fragment identifier (%s)',
319     level => 'warn',
320     },
321 wakaba 1.4 ## XML warning
322 wakaba 1.1 WARN_PREDEFINED_ENTITY_NOT_DECLARED => {
323     description => 'Predefined general entity (%s) should be declared before it is referred for interoperability',
324     level => 'warn',
325     },
326     WARN_UNICODE_COMPAT_CHARACTER => {
327     description => sub {
328     my $r = sprintf 'Use of the character U+%04X is deprecated, since it is classified as compatible character in the Unicode Standard',
329     $_[1]->{t};
330     $_[1]->{t} = undef;
331     $r;
332     },
333     level => 'warn',
334     },
335     WARN_UNICODE_NONCHARACTER => {
336     description => sub {
337     my $r = sprintf 'Use of the code point U+%04X is deprecated, since it is noncharacter in the Unicode Standard',
338     $_[1]->{t};
339     $_[1]->{t} = undef;
340     $r;
341     },
342     level => 'warn',
343     },
344     WARN_UNICODE_XML_NOT_SUITABLE_CHARACTER => {
345     description => sub {
346     my $r = sprintf 'Use of the character U+%04X is deprecated by W3C Note unicode-xml',
347     $_[1]->{t};
348     $_[1]->{t} = undef;
349     $r;
350     },
351     level => 'warn',
352     },
353     WARN_UNIQUE_ENTITY_NAME => {
354     description => 'General entity %s is already declared',
355     level => 'warn',
356     },
357     WARN_UNIQUE_PARAMETER_ENTITY_NAME => {
358     description => 'Parameter entity %s is already declared',
359     level => 'warn',
360     },
361 wakaba 1.5 ## XMLName recommendation
362     WARN_XML_NS_URI_IS_RELATIVE => {
363     description => 'URI of XML Namespace name is a relative URI',
364     level => 'warn',
365     },
366 wakaba 1.3 ## RFC 3023 'SHOULD'
367     WARN_MT_DTD_EXTERNAL_SUBSET => {
368     description => q(Media type "application/xml-dtd" SHOULD be used for the external subset of the DTD or the external parameter entity),
369     level => 'warn',
370     },
371     WARN_MT_EXTERNAL_GENERAL_PARSED_ENTITY => {
372     description => q(Media type "application/xml-external-parsed-entity" SHOULD be used for the external general parsed entity),
373     level => 'warn',
374     },
375     WARN_MT_XML_FOR_EXT_GENERAL_ENTITY => {
376     description => 'Using media type %s for external general parsed entity is now forbidden unless the entity is also well-formed as a document entity',
377     level => 'warn',
378     },
379 wakaba 1.1 ## Implementation's warning
380 wakaba 1.4 WARN_DOCTYPE_NOT_FOUND => {
381     description => 'No document type definition provided for this document',
382     level => 'warn',
383     },
384     WARN_ENTITY_DECLARATION_NOT_PROCESSED => {
385     description => 'This entity declaration is not processed because unread parameter entity is referred before this declaration',
386     level => 'warn',
387     },
388     WARN_EXTERNALLY_DEFINED_ENTITY_REFERRED => {
389     description => 'The entity referred (%s) is declared in the external entity, so different groove can be constructed when external entity is not read',
390     level => 'warn',
391     },
392 wakaba 1.3 WARN_GUESS_ENCODING_IMPL_ERR => {
393     description => 'Guessing encoding procedure cause some error (%s)',
394     level => 'warn',
395     },
396 wakaba 1.5 WARN_INVALID_URI_CHAR_IN_NS_NAME => {
397     description => 'URI of XML Namespace name contains at least one non-URI character',
398     level => 'warn',
399     },
400 wakaba 1.3 WARN_INVALID_URI_CHAR_IN_SYSID => {
401     description => 'System identifier has at least one character that is invalid as part of URI Reference (%s)',
402     level => 'warn',
403     },
404     WARN_MT_TEXT_XML => {
405     description => q(In many case, labeling with the media type "text/xml" is inappropriate. Use "application/xml" or markup language specified type instead),
406     level => 'warn',
407     },
408     WARN_MT_TEXT_XML_EXTERNAL_PARSED_ENTITY => {
409     description => q(In many case, labeling with the media type "text/xml-external-parsed-entity" is inappropriate. Use "application/xml-external-parsed-entity" instead),
410     level => 'warn',
411     },
412     WARN_NO_CHARSET_PARAM => { ## charset parameter is optional
413     description => 'Charset parameter should be specified (%s)',
414     level => 'warn',
415     },
416     WARN_NO_CHARSET_PARAM_FOR_TEXT => { ## charset parameter have default value of ascii
417     description => q(Charset parameter is not specified, so default value 'us-ascii' is assumed (%s)),
418     level => 'warn',
419     },
420     WARN_NO_EXPLICIT_ENCODING_INFO => { ## BOM and '<?' guessing is failed (so general encoding guess is to be called)
421     description => q(Neither upper level protocol nor XML's encoding declaration provide encoding scheme information (or cannot read the encoding declaration because of lack of guessability)),
422     level => 'warn',
423     },
424 wakaba 1.4 WARN_PI_TARGET_NOTATION => {
425     description => 'Target name of the process instruction (%s) should be declared as a notation name to ensure interoperability',
426     level => 'warn',
427     },
428     WARN_PID_EMPTY => {
429     description => 'Public identifier is empty',
430     level => 'warn',
431     },
432 wakaba 1.3 WARN_PID_IS_INVALID_URN => {
433     description => 'Public identifier (%s) seems an invalid URN',
434     level => 'warn',
435     },
436     WARN_PID_IS_NOT_FPI_NOR_URN => {
437     description => 'Public identifier (%s) should be a formal public identifier or a uniform resource name to ensure interoperability',
438     level => 'warn',
439     },
440     WARN_PID_IS_TOO_LONG => {
441     description => 'Public identifier (%s) should be shorter for interoperability',
442     level => 'warn',
443     },
444     WARN_PID_IS_URN_WITH_RESERVED_CHAR => {
445     description => 'Public identifier (%s) seems a URN and it contains one or more reserved character ("/" and/or "?") which should not be used',
446     level => 'warn',
447     },
448 wakaba 1.4 WARN_SYSID_EMPTY => {
449     description => 'System identifier is empty, in most case it is wrong',
450     level => 'warn',
451     },
452 wakaba 1.3 WARN_XML_DECLARE_NO_VERSION_ATTR => {
453     description => 'Text declaration does not have the version pseudo attribute',
454     level => 'warn',
455     },
456 wakaba 1.1 ## Misc
457     UNKNOWN => {
458     description => 'Unknown error',
459 wakaba 1.3 level => 'fatal',
460 wakaba 1.1 },
461     );
462 wakaba 1.6
463 wakaba 1.1 sub raise ($$%) {
464 wakaba 1.6 my ($caller, $o, %err) = @_;
465 wakaba 1.1 my $error_type = $_Error{$err{type}} || $_Error{UNKNOWN};
466     my $error_msg = ref $error_type->{description} ? &{$error_type->{description}} ($o, \%err)
467     : $error_type->{description};
468     my @err_msg;
469     ref $err{t} eq 'ARRAY' ? @err_msg = @{$err{t}} : defined $err{t} ? @err_msg = $err{t} : undef;
470     $error_msg .= ' (%s)' if scalar (@err_msg) && ($error_msg !~ /%s/);
471 wakaba 1.6 $error_msg = sprintf 'Entity %s <%s>: line %d position %d: '.$error_msg,
472     ($err{entity}||$o->{entity}||'#document'),
473     $o->{uri}, $o->{line}, $o->{pos}, @err_msg;
474     my $resolver = $caller->option ('error_handler');
475     if (ref $resolver) {
476     $resolver = &$resolver ($caller, $o, $error_type, $error_msg); ## If returned false,
477     &_default_error_handler ($caller, $o, $error_type, $error_msg)
478     if $resolver; ## don't call this.
479     } else {
480     &_default_error_handler ($caller, $o, $error_type, $error_msg);
481     }
482     }
483    
484     sub _default_error_handler ($$$$) {
485     my ($caller, $o, $error_type, $error_msg) = @_;
486     require Carp;
487     if ({qw/fatal 1 wfc 1 nswfc 1/}->{$error_type->{level}}) {
488     Carp::croak ($error_msg);
489     } else {
490     Carp::carp ($error_msg);
491     }
492     }
493    
494     =head1 ERROR REPORTING WITH NODE INFORMATION
495    
496     =over 4
497    
498     =item $err = SuikaWiki::Markup::XML::Error->new ({error definitions})
499    
500     Constructs new error reporting object. Hash reference to error definition list (like %_Error
501     defined in this module) must be specified as an argument.
502    
503     =cut
504    
505     sub new ($$) {
506     my $class = shift;
507     bless shift, $class;
508     }
509    
510     =item $err->raise_error ($node, %detail)
511    
512     Raises an error (or a warning, if defined so)
513    
514     =cut
515    
516     sub raise_error ($$%) {
517     my ($self, $node, %err) = @_;
518     my $error_type = $self->{$err{type}} || $self->{UNKNOWN};
519     my $error_msg = ref $error_type->{description} ? &{$error_type->{description}} ($node, \%err)
520     : $error_type->{description};
521     my @err_msg;
522     ref $err{t} eq 'ARRAY' ? @err_msg = @{$err{t}} : defined $err{t} ? @err_msg = $err{t} : undef;
523     $error_msg .= ' (%s)' if scalar (@err_msg) && ($error_msg !~ /%s/);
524 wakaba 1.1 $error_msg = sprintf $error_msg, @err_msg;
525 wakaba 1.6 $err{node_path} = $self->_get_node_path ($node) if $node;
526    
527     my $resolver = $self->{-error_handler};
528     if (ref $resolver) {
529     $resolver = &$resolver ($self, $node, $error_type, $error_msg, \%err); ## If returned false,
530     $self->_default_error_handler_2 ($node, $error_type, $error_msg, \%err)
531     if $resolver; ## don't call this.
532     } else {
533     $self->_default_error_handler ($node, $error_type, $error_msg, \%err);
534     }
535     }
536    
537     sub _default_error_handler_2 ($$$$$) {
538     my ($self, $node, $error_type, $error_msg, $err) = @_;
539 wakaba 1.1 require Carp;
540 wakaba 1.6 $error_msg = $err->{node_path} . ': ' . $error_msg if $err->{node_path};
541     $error_msg = 'Document <'.$err->{uri}.'>: ' . $error_msg if $err->{uri};
542     if ({qw/fatal 1 nswfc 1/}->{$error_type->{level}}) {
543     Carp::croak ($error_msg);
544     } else {
545     Carp::carp ($error_msg);
546     }
547     }
548    
549     sub _get_node_path ($$) {
550     my ($self, $node) = @_;
551     my $nn = '';
552     my $nt = $node->node_type;
553     my $nnsuri = $node->namespace_uri;
554     my $nlname = $node->local_name;
555     if ($nt eq '#element') {
556     $nn = $node->qname
557     . $self->_get_node_position ($node, namespace_uri => $nnsuri, local_name => $nlname,
558     type => $nt);
559     } elsif ($nt eq '#attribute') {
560     $nn = '@' . $node->qname;
561     } elsif ($nt eq '#text' || $nt eq '#comment') {
562     $nn = 'smxe:'.substr ($nt, 1) . '()' . $self->_get_node_position ($node, type => $nt);
563     } elsif ($nt eq '#pi') {
564     $nn = 'smxe:pi("' . $nlname . '")'
565     . $self->_get_node_position ($node, local_name => $nlname, type => $nt);
566     } elsif ($nt eq '#section') {
567     my $nstatus = $node->get_attribute ('status', make_new_node => 1)->inner_text||'INCLUDE';
568     $nn = 'smxe:section("'.$nstatus.'")'
569     . $self->_get_node_position ($node, status => $nstatus, type => $nt);
570     } elsif ($nt eq '#declaration') {
571     $nn = 'smxe:declaration('.
572     ({split /\s+/, qq/$NS{SGML}attlist "ATTLIST"
573     $NS{SGML}doctype "DOCTYPE"
574     $NS{SGML}element "ELEMENT"
575     $NS{SGML}entity "ENTITY"
576     $NS{SGML}notation "NOTATION"/}->{$nnsuri}||'smxe:ns("'.$nnsuri.'")')
577     .')' . $self->_get_node_position ($node, namespace_uri => $nnsuri,
578     local_name => $nlname, type => $nt);
579     } elsif ($nt eq '#reference') {
580     $nn = 'smxe:ref('.
581     ({split /\s+/, qq/$NS{SGML}char:ref "char"
582     $NS{SGML}char:ref:hex "char"
583     $NS{SGML}entity "general"
584     $NS{SGML}entity:parameter "parameter"/}->{$nnsuri}||'smxe:ns("'.$nnsuri.'")')
585     .($nlname ? ', "'.$nlname.'"':'')
586     .')' . $self->_get_node_position ($node, namespace_uri => $nnsuri,
587     local_name => $nlname, type => $nt);
588     } elsif ($nt eq '#document') {
589     $nn = '/';
590     } elsif ($nt eq '#fragment') {
591     $nn = 'smxe:fragment()' . $self->_get_node_position ($node, type => $nt);
592     } elsif ($nt eq '#xml') {
593     $nn = 'smxe:xml()' . $self->_get_node_position ($node, type => $nt);
594     } else {
595     $nn = 'smxe:x-unknown("'.$nt.'")' . $self->_get_node_position ($node, type => $nt);
596     }
597     $nn = $self->_get_node_path ($node->parent_node) . '/' . $nn if $node->parent_node;
598     $nn = substr ($nn, 1) if substr ($nn, 0, 2) eq '//';
599     $nn;
600     }
601    
602     sub _get_node_position ($$%) {
603     my ($self, $node, %prop) = @_;
604     my $node_str = overload::StrVal ($node);
605     if ($node->parent_node) {
606     my $i = 1;
607     for (@{$node->parent_node->child_nodes}) {
608     if ($node_str eq overload::StrVal ($_)) {
609     return '[smxe:position()='.$i.']';
610     } elsif (($prop{type} eq $_->node_type)
611     && (defined $prop{namespace_uri} ? ($prop{namespace_uri} eq $_->namespace_uri) : 1)
612     && (defined $prop{local_name} ? ($prop{local_name} eq $_->local_name) : 1)
613     && (defined $prop{status} ? ($prop{status} eq ($_->get_attribute
614     ('status', make_new_node => 1)->inner_text
615     || 'INCLUDE')) : 1)
616     ) {
617     $i++;
618     }
619     }
620     return '[smxe:error()]';
621     } else {
622     return '';
623     }
624 wakaba 1.1 }
625    
626     =head1 LICENSE
627    
628     Copyright 2003 Wakaba <[email protected]>
629    
630     This program is free software; you can redistribute it and/or
631     modify it under the same terms as Perl itself.
632    
633     =cut
634    
635 wakaba 1.6 1; # $Date: 2003/06/30 11:06:28 $

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24