Re: Parameter Calculations and Removing Complexity

Hi Alex,

Alex Milowski wrote:
> But... since you can easy set parameter values on the pipeline and have
> those cascade into the XSLT step, you can easily pass configuration
> *string* parameters into your XSLT transform.

As long as they have the same name, yes. But what if you don't want the 
names of the parameters in your stylesheet to be the same as the names 
of the parameters of your pipeline?

Perhaps I'm approaching these the wrong way, but here are two real-world 
examples where parameter values are calculated. In fact, these 
parameters aren't XSLT parameters, but I don't think that matters.

First, accessing documents whose URIs are kept in a manifest.

  <p:pipeline>
    <p:declare-input port="manifest" />
    <p:declare-output port="results" sequence="yes"
                      step="load-documents" source="result" />
    <p:for-each name="load-documents">
      <p:declare-input port="file-ref"
                       source="manifest"
                       select="/files/file" />
      <p:declare-output port="result"
                        step="load-document" source="result" />
      <p:step name="load-document" type="p:load">
        <p:param name="href"
                 source="file-ref"
                 select="@href" />
      </p:step>
    </p:for-each>
  </p:pipeline>

Second, documenting XSLT. I want to have a pipeline that creates HTML 
documentation from a given stylesheet. If the URI for the HTML 
documentation isn't specified by the person running the pipeline, then I 
want it to default to the name of the stylesheet with a '.html' extension.

I can think of two ways of doing this: passing in the URI of the 
stylesheet as a parameter to the pipeline, and parsing that URI to 
create the URI for the HTML documentation:

  <p:pipeline>
    <p:declare-param name="stylesheet-uri" />
    <p:declare-param name="documentation-uri"
      select="substring($stylesheet-uri, 1,
                        string-length($stylesheet-uri) - 4)" />
    <p:step name="load-stylesheet" type="p:load">
      <p:param name="href" select="$stylesheet-uri" />
    </p:step>
    ...
    <p:step name="save-documentation" type="p:save">
      <p:input name="documents" ... />
      <p:param name="href" select="$documentation-uri" />
    </p:step>
  </p:pipeline>

or using base-uri() to get it. Assuming that we're not supporting XPath 
2.0, I need a separate component to do that:

  <p:pipeline>
    <p:declare-input port="stylesheet" />
    <p:declare-param name="documentation-uri" value="" />
    ...
    <p:choose>
      <p:when test="$documentation-href = ''">
        <p:step name="get-base-uri" type="p:xpath2.0">
          <p:input port="context" source="stylesheet" />
          <p:param name="xpath"
            value="replace(base-uri(.), '\.xsl$', '.html')" />
        </p:step>
        <p:step name="save-documentation" type="p:save">
          <p:param name="href"
                   step="get-base-uri" source="result"
                   select="/xpath:result" />
        </p:step>
      </p:when>
      ...
    </p:choose>
  </p:pipeline>

> You will *not* be able to pass elements as parameters to the
> transformation and so would need generate an input transformation to do
> that.  Once you have an input that is your configuration of a
> transformation, the next likely step is to pass XML structures.  That
> means that 'step/source/select' on [p:]param will fail to be
> useful there and you'll be required to generate a transformation
> on the fly that imports your regular XSLT.

Yes. Most XSLT processors don't give you an easy way of passing in 
anything but strings for parameters (from the command line), so I'm used 
to designing transformations where instead of passing in the XML 
configuration itself, I pass in the URI for its file.

Translated into XProc, this leads to problems with step ordering. If I do:

  <p:step name="save-config" type="p:save">
    <p:input port="document" ... />
    <p:param name="href" select="$config-uri" />
  </p:step>
  <p:step name="transform" type="p:xslt">
    <p:input port="source" ... />
    <p:input port="stylesheet" ... />
    <p:param name="doc-template-uri" select="$config-uri" />
  </p:step>

but don't have a way (such as the order of the steps) of indicating that 
actually the 'transform' step is dependent on 'save-config' then my 
final result will be implementation-dependent.

As you say, an alternative design is to generate a stylesheet that sets 
the parameter. Wanting to avoid extensions, with XSLT 1.0 you'd have to 
copy the configuration XML into the generated stylesheet and use 
document('') to get it.

I'm waiting for a better way.

Cheers,

Jeni
-- 
Jeni Tennison
http://www.jenitennison.com

Received on Wednesday, 4 October 2006 20:06:37 UTC