The logo is a pig framed between two angle brackets.

Grouping With <p:group/>

Combining code blocks into groups can have various advantages: you can reduce complexity, encapsulate functionality and make the code easier to read. Therefore, XProc allows you to group different steps and combine them in a subpipeline with the compound step p:group.

XProc’s concept of grouping is straightforward: You wrap the steps in a p:group. The input of the first step and the output of the last steps serve as input and output of the subpipeline but you are free to declare individual output ports and connect them to steps in the group. The output ports of steps within a group are not visible to steps outside and can only be exposed through the output ports of the group. Steps within the group can reference ports from steps outside as long as they are not included in a group themselves.

Let’s demonstrate this concept with XProc: Suppose we have an XML representation of an automobile manufacturing process and want to add various features. We wrap the production steps in a p:group:


<?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>
      <my-car/>
    </p:inline>
  </p:input>
  
  <p:output port="result"/>
  
  <p:group name="car-features">
    
    <p:add-attribute attribute-name="paint" 
                     attribute-value="red"/>
    
    <p:add-attribute attribute-name="engine" 
                     attribute-value="electric"/>
    
    <p:add-attribute attribute-name="extras" 
                     attribute-value="bobblehead"/>
    
  </p:group>
  
</p:declare-step>

Output

<?xml version="1.0" encoding="UTF-8"?>
<my-car extras="bobblehead" engine="electric" paint="red"/>

Now let’s assume we want to see the snapshot of the car just after the paint job has been added. In addition to the full output, we add another secondary output called paint. But there is a problem: Steps within a group are not visible outside of the group. In order to connect the output of the first p:add-attribute with our secondary port, we need to declare a primary and a secondary output for the group through which we route the data from within the group to the outside:

<?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>
      <my-car/>
    </p:inline>
  </p:input>
  
  <p:output port="result" primary="true"/>
  
  <p:output port="paint" primary="false">
    <p:pipe port="paint" step="car-features"/>
  </p:output>
  
  <p:group name="car-features">
    <p:output port="result" primary="true"/>
    <p:output port="paint" primary="false">
      <p:pipe port="result" step="add-paint"/>
    </p:output>
    
    <p:add-attribute attribute-name="paint" 
                     attribute-value="red" name="add-paint"/>
    
    <p:add-attribute attribute-name="engine" 
                     attribute-value="electric"/>
    
    <p:add-attribute attribute-name="extras" 
                     attribute-value="bobblehead"/>
    
  </p:group>
  
</p:declare-step>

Output: result

<?xml version="1.0" encoding="UTF-8"?>
<my-car extras="bobblehead" engine="electric" paint="red"/>

Output: paint

<?xml version="1.0" encoding="UTF-8"?>
<my-car paint="red"/>

Read more…