The logo is a pig framed between two angle brackets.

XProc 3.0 Tutorial

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>

Read more…