Error Handling With <p:try/>
There are various exceptions that can cause a pipeline to fail: a document failed to load, a schema validation fails, or the output generated by one step does not match the input requirements of the following step. You can also intentionally crash a pipeline with the p:error
step. If you want to catch these errors and continue the pipeline, you can help yourself with p:try
.
Like other programming languages, XProc offers a try/catch/finally method:
(1) The p:try
contains an initial subpipeline wrapped in a p:group
. In case there are no errors, the outputs of that pipeline are the outputs of the p:try
step.
(2) If any errors occur and there is a p:catch
branch, this subpipeline is executed and becomes the output of p:try
. If there are multiple p:catch
branches, all but the last p:catch
must contain an @error
attribute in order the appropriate error branch could be selected for the given error code. In case there is no p:catch
that matches the error code, the last p:catch
is evaluated.
(3) However, if there is a p:finally
available, this subpipeline will be executed regardless whether the initial pipeline or the p:catch
succeeds or fails. p:finally
must not yield any outputs because its considered for clean-up tasks that should not interfere with the outputs of either the initial subpipeline or the p:catch
branch.
The pipeline below includes a p:error
step causing the initial pipeline to fail. Then the p:catch
branch is executed which just generates an error message. After the catch-branch, the p:finally
is started that includes a step without an output port.
<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0">
<p:input port="source">
<p:inline>
<doc>Hello XPorc!</doc>
</p:inline>
</p:input>
<p:output port="result"/>
<p:try>
<p:group>
<p:error code="error-raised-by-myself"/>
</p:group>
<p:catch>
<p:identity>
<p:with-input>
<p:inline>
<err>An error occurred!</err>
</p:inline>
</p:with-input>
</p:identity>
</p:catch>
<p:finally>
<p:sink name="do-nothing"/>
</p:finally>
</p:try>
</p:declare-step>
Output
<?xml version="1.0" encoding="UTF-8"?> <err>An error occurred!</err>
The Error Port
The p:catch
has an input port named error
. Errors produced by steps are passed as messages to this port and can be used as input to steps within p:catch
. In the example below, we pipe the error message to the output, which can be useful for displaying the errors to the user later.
<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0">
<p:output port="result"/>
<p:try>
<p:group>
<p:load href="this-should-be-the-path/my-file.xml"/>
</p:group>
<p:catch name="my-catch">
<p:identity>
<p:with-input pipe="error@my-catch"/>
</p:identity>
</p:catch>
</p:try>
</p:declare-step>
Output
<?xml version="1.0" encoding="UTF-8"?> <c:errors xmlns:c="http://www.w3.org/ns/xproc-step"> <c:error code="err:XD0011" href="my-pipeline.xpl" line="9" column="59" xmlns:err="http://www.w3.org/ns/xproc-error">Error while loading. Resource not found: C:\this-should-be-the-path\my-file.xml </c:error> </c:errors>