Revised parameters proposal

This proposal is my proposal from a few days ago adjusted to address
the comments made by Alex, Henry, and Jeni.

1. No more automatic inheritance. Consequently, remove parameters
   from compound steps.

2. Add a grouping mechanism, a la XSLT attribute sets:

   <p:parameter-set
     name = NCName>
    (p:inline|p:pipe|p:document|p:parameter*)
   </p:parameter-set>

   For V1, I propose that p:parameter-set be allowed only as a child
   of p:pipeline.

   If the same parameter is specified more than once inside a
   p:parameter-set, the last value specified is used.

   Having sets isn't very useful if you can't use them, so we also
   need @use-parameter-sets on steps. (For steps not in the pipeline
   namespace, that's spelled @p:use-parameter-sets.)

   If more than one parameter set is named in a
   use-parameter-sets, then the parameters from each set are
   merged, in the order specified. In the case of duplicate
   names, the last value is used.

   Consider:

   <p:parameter-set name="seta">
     <p:parameter name="aname" value="1"/>
     <p:parameter name="pname" value="foo"/>
   </p:parameter-set>

   <p:parameter-set name="setb">
     <p:parameter name="bname" value="2"/>
     <p:parameter name="pname" value="bar"/>
   </p:parameter-set>

   <p:xslt use-parameter-sets="seta setb">
     ...
   <p:xslt>

   The parameters passed to the XSLT step are:

     aname=1
     bname=2
     pname=bar

   If use-parameter-sets="setb seta" had been specified, then
   the parameters passed would have been:

     aname=1
     bname=2
     pname=foo

   The ability to group parameters gives the pipeline author control
   over all the parameters *except* those that are passed to the
   pipeline (either by the application, e.g., from the command line
   or by the invocation of the pipeline from some other pipeline).

   I propose that we address that by allowing "#top-level" as a
   parameter set name. It means "all the parameters passed to the
   p:pipeline", which might be the empty set.

   Users can merge parameter sets by specifying
   use-parameter-sets on a p:parameter-set element. Users can
   control whether the "used value" or the "declared value" has
   priority by specifying inherit=yes|no on the p:parameter. The
   default is 'yes'.

   Using sets 'seta' and 'setb' from above:

    <p:parameter-set name="setc" use-parameter-sets="seta">
      <p:parameter name="aname" value="3"/>
    </p:parameter-set>

   results in aname=1 in 'setc'. Conversely:

    <p:parameter-set name="setd" use-parameter-sets="seta">
      <p:parameter name="aname" value="3" inherit='no'/>
    </p:parameter-set>

   results in aname=3 in 'setd'. The inherit attribute has no effect
   if there is no duplication.

   This feature gives pipeline authors control over whether parameters
   passed in the '#top-level' set (over which they have no control) are
   more or less important than the values they set explicitly.

3. If a p:inline, p:pipe, or p:document occurs inside a
   p:parameter-set, it must produce a sequence of c:parameter
   documents. It is a dynamic error if anything else appears.

   Each c:parameter document must consist of:

   <c:parameter
      name = string
      namespace? = anyURI
      value = string/>

   If name has the lexical form of an NCName then, if namespace
   is specified, then it is a QName in that namespace, otherwise
   it is in no namespace. If name is not an NCName then it must
   have the lexical form of a QName. If it has the lexical form
   of a QName, then the namespace bindings associated with the
   c:parameter element are used to evaluated it. It is a dynamic
   error if name contains a colon and namespace is specified.

   It is a dynamic error if a p:pipe points to a step
   that (directly or indirectly) uses the parameter set being
   defined.

4. One case that we expect to be common is that a pipeline has no
   explicit parameters but that user-specified top-level
   parameters should be passed to steps.

   In order to achieve this, we say that the default value of
   use-parameter-sets (or p:use-parameter-sets) on a step is
   "#top-level".

5. In order to give the pipeline access to the top level parameters,
   we add a new step:

   <p:declare-step type="p:parameters">
     <p:output port="result" sequence="yes" />
   </p:declare-step>

   This step produces on its output port a sequence of
   c:parameter documents, one for each parameter passed to it. By
   point 4 above, this will by default be the #top-level
   parameters, though pipeline authors will be free to use this
   for other sets.

   The c:parameter elements produced by this step always have names
   that are NCNames.

What does this mean?

Consider the simplest case:

  <p:pipeline>
    ...
    <p:xslt>
      <p:input port="source">...</p:input>
      <p:input port="stylesheet">...</p:input>
    </p:xslt>
  </p:pipeline>

Today, any parameters passed to the pipeline are automatically
available to the XSLT step. To obtain that behavior under this
proposal, no changes would have to be made to the pipeline!

If there were any legacy pipelines, and those legacy pipelines
relied on parameters set on p:group elements scoping the
parameters used inside the group, they'd have to be changed from:

  <p:pipeline>
    ...
    <p:group>
      <p:option name="baz" select="concat($moo,'-1')"/>
      <p:parameter name="foo" value="bar"/>

      <p:xslt>
        <p:input port="source">...</p:input>
        <p:input port="stylesheet">...</p:input>
        <p:parameter name="base-name" select="$baz"/>
      </p:xslt>
      <px:something-else/>
    </p:group>
  </p:pipeline>

to something like this:

  <p:pipeline>
    <p:parameter-set name="group1" use-parameter-sets="#top-level">
      <p:parameter name="foo" value="bar"/>
    </p:parameter-set>
    ...
    <p:group>
      <p:option name="baz" select="concat($moo,'-1')"/>

      <p:xslt use-parameter-sets="group1">
        <p:input port="source">...</p:input>
        <p:input port="stylesheet">...</p:input>
        <p:parameter name="base-name" select="$baz"/>
      </p:xslt>
      <px:something-else p:use-parameter-sets="group1"/>
    </p:group>
  </p:pipeline>

Pipelines that need to perform more complex computations can do so:

  <p:pipeline>
    <p:parameter-set name="global">
      <p:pipe port="result" step="load-global"/>
      <p:pipe port="result" step="some-top-level"/>
    </p:parameter-set>

    <p:try name="load-global">
      <p:group>
        <p:output port="result"/>
        <p:load>
          <p:option name="href" value="~/.globals.xml"/>
        </p:load>
      </p:group>
      <p:catch>
        <p:output port="result"/>
        <p:identity>
          <p:input port="source">
            <p:inline>
              <c:parameters/>
            </p:inline>
          </p:input>
        </p:identity>
      </p:catch>
    </p:try>

    <p:parameters use-parameter-sets="#top-level"/>

    <p:matching-documents name="some-top-level">
      <p:option name="test" value="@namespace = 'http://example.com/'"/>
    </p:matching-documents>

    <p:xslt use-parameter-sets="global #top-level">
      ...
    </p:xslt>
  </p:pipeline>

I believe this proposal will satisfy Alex, Henry, Jeni, and
myself, at least!

                                        Be seeing you,
                                          norm

-- 
Norman Walsh <ndw@nwalsh.com> | To buy books would be a good thing if
http://nwalsh.com/            | we could also buy the time to read
                              | them; as it is, the mere act of
                              | purchasing them is often mistaken for
                              | the assimilation and mastering of their
                              | content.-- Schopenhauer

Received on Wednesday, 6 June 2007 17:16:11 UTC