/[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.7 - (hide annotations) (download)
Sat Jul 12 06:12:00 2003 UTC (23 years ago) by w
Branch: MAIN
Changes since 1.6: +103 -13 lines
ELEMENT and ATTLIST declaration support reimplemented

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24