Search code examples
xmlpipelinesaxonxproc

How to simplify this xproc pipeline?


I've just started digging into XProc (using Calabash). I have a series of XSLT transformations I want to apply to a single input document to produce a single output document. I was previously using a simple Python script to drive the transformations, but it seemed like XProc might be a good fit.

The pipeline below seems to work for me. It's essentially just a list of the XSLT transformations that need to be applied, in the correct order. The problem is, it seems mighty redundant. I'm hoping there's some way to cut down on that, but (so far) I can't figure it out on my own.

<?xml version="1.0"?>
<p:pipeline version="1.0" xmlns:p="http://www.w3.org/ns/xproc">
    <p:xslt name="remove-locations">
        <p:input port="stylesheet">
            <p:document href="preprocessors/remove-locations.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="divisions-1">
        <p:input port="stylesheet">
            <p:document href="preprocessors/divisions-1.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="divisions-2">
        <p:input port="stylesheet">
            <p:document href="preprocessors/divisions-2.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="subjects-1">
        <p:input port="stylesheet">
            <p:document href="preprocessors/subjects-1.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="subjects-2">
        <p:input port="stylesheet">
            <p:document href="preprocessors/subjects-2.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="types-1">
        <p:input port="stylesheet">
            <p:document href="preprocessors/types-1.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="types-2">
        <p:input port="stylesheet">
            <p:document href="preprocessors/types-2.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="core">
        <p:input port="stylesheet">
            <p:document href="preprocessors/core.xsl"/>
        </p:input>
    </p:xslt>

    <p:xslt name="consolidate-descriptions">
        <p:input port="stylesheet">
            <p:document href="preprocessors/consolidate-descriptions.xsl"/>
        </p:input>
    </p:xslt>
</p:pipeline>

Solution

  • I turned to the xproc-dev mailing list for help, and a solution was quickly proposed and implemented for me. This allowed me to simplify the above pipeline down to this (namespaces changed to protect the innocent):

    <?xml version="1.0"?>
    <p:pipeline
        version="1.0"
        xmlns:p="http://www.w3.org/ns/xproc"
        xmlns:ex="http://example.com">
    
        <p:declare-step type="ex:xslt" name="xslt">
            <p:input port="source" sequence="true" primary="true"/>
            <p:input port="parameters" kind="parameter"/>
            <p:output port="result" primary="true"/>
            <p:option name="stylesheet" required="true"/>
    
            <p:load name="load-stylesheet">
                <p:with-option name="href" select="$stylesheet"/>
            </p:load>
    
            <p:xslt>
                <p:input port="stylesheet">
                    <p:pipe port="result" step="load-stylesheet"/>
                </p:input>
                <p:input port="source">
                    <p:pipe port="source" step="xslt"/>
                </p:input>
            </p:xslt>
        </p:declare-step>
    
        <ex:xslt stylesheet="remove-locations.xsl"/>
        <ex:xslt stylesheet="divisions-1.xsl"/>
        <ex:xslt stylesheet="divisions-2.xsl"/>
        <ex:xslt stylesheet="subjects-1.xsl"/>
        <ex:xslt stylesheet="subjects-2.xsl"/>
        <ex:xslt stylesheet="types-1.xsl"/>
        <ex:xslt stylesheet="types-2.xsl"/>
        <ex:xslt stylesheet="core.xsl"/>
        <ex:xslt stylesheet="consolidate-descriptions.xsl" />
    </p:pipeline>
    

    (I actually separated the step out into its own file and <p:import> it, so the main pipeline file is even simpler than that.)