4.4 Error Handling

When encountering an error. the ‘gamma xml’ functions use Guile error reporting mechanism (see Procedures for Signaling Errors: (guile)Error Reporting section `Error Reporting' in The Guile Reference Manual). The error key indicates what type of error it was, and the rest of arguments supply additional information about the error. Recommended ways for handling errors in Guile are described in How to Handle Errors: (guile)Handling Errors section `Handling Errors' in The Guile Reference Manual). In this chapter we will describe how to handle errors in XML input and other errors reported by the underlying ‘libexpat’ library.

Error Key: gamma-xml-error

An error of this type is signalled when a of ‘gamma xml’ functions encounters an XML-related error.

The arguments supplied with this error are:

key

The error key (gamma-xml-error).

func

Name of the function that generated the error.

fmt

Format string

fmt-args

Arguments for ‘fmt’.

descr

Error description. If there are no additional information, it is #f. Otherwise it is a list of 5 elements which describes the error and its location in the input stream:

  1. Error code (number).
  2. Line number (starts at 1).
  3. Column number (starts at 0).
  4. Context in which the error occurred, i.e. a part of the input text which was found to contain the error.
  5. Offset of point that caused the error within the context.

A special syntax is provided to extract parts of the ‘descr’ list:

Gamma Syntax: xml-error-descr descr key

Extract from descr the part identified by key. Use this macro in the error handlers. Valid values for key are:

xml-error-descr key: #:error-code

Return the error code.

xml-error-descr key: #:line

Return line number.

xml-error-descr key: #:column

Return column number.

xml-error-descr key: #:has-context?

Return #t if the description has context part. Use the two keywords below only if

 
(xml-error-descr d #:has-context?

returned #t.

xml-error-descr key: #:context

Return context string.

xml-error-descr key: #:error-offset

Return the location within #:context where the error occurred.

If no special handler is set, the default guile error handler displays the error and its approximate location on the standard error port. For example, given the following input file:

 
$ cat input.xml
<input>
 <ref a=1/>
</input>

the ‘xmlck.scm’ (see xmlck.scm) produces:

 
$ guile -s examples/xmlck.scm < input.xml
ERROR: In procedure xml-primitive-parse:
ERROR: not well-formed (invalid token) near line 2

To provide a more detailed diagnostics, catch the gamma-xml-error code and use information from the ‘descr’ list. For example:

 
(catch 'gamma-xml-error
       (lambda ()
	 (xml-parse (xml-make-parser)))
       (lambda (key func fmt args descr)
	 (with-output-to-port
	     (current-error-port)
	   (lambda ()
	     (cond
	      ((not descr)
	       (apply format #t fmt args)
	       (newline))
	      (else
	       (format #t
		       "~A:~A: ~A~%"
		       (xml-error-descr descr #:line)
		       (xml-error-descr descr #:column)
		       (xml-error-string (xml-error-descr descr #:error-code)))
	       (if (xml-error-descr descr #:has-context?)
		   (let ((ctx-text (xml-error-descr descr #:context))
			 (ctx-pos  (xml-error-descr descr #:error-offset)))
		     (format #t
			     "Context (^ marks the point): ~A^~A~%"
			     (substring ctx-text 0 ctx-pos)
			     (substring ctx-text ctx-pos))))
	       (exit 1)))))))

When applied to the same input document as in the previous example, this code produces:

 
$ guile -s examples/xml-check.scm < input.xml
2:8: not well-formed (invalid token)
Context (^ marks the point): <input>
 <ref a=^1/>