Re: Revised parameters proposal

I think we're getting there. A few more comments from me.

Norman Walsh wrote:
> 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.

Is it allowed between steps or only before the subpipeline? I think the 
latter will be hard to use, so I hope it's the former.

In fact, I'm not all that convinced that parameter sets will get much 
reuse, so rather than forcing people to do:

<p:pipeline ...>
   ...
   <p:parameter-set name="my-xslt-parameters">
     <p:pipe step="foo" source="result" />
     <p:parameter name="view" value="default" />
   </p:parameter-set>
   ...
   <p:xslt use-parameter-sets="my-xslt-parameters">
     ...
   </p:xslt>
</p:pipeline>

I think we should allow:

<p:pipeline ...>
   ...
   <p:xslt>
     ...
     <p:parameter-set>
       <p:pipe step="foo" source="result" />
       <p:parameter name="view" value="default" />
     </p:parameter-set>
   </p:xslt>
</p:pipeline>

The proximity of the construction of the parameter set and the use of 
the parameter set will help users.

[In fact, I think that <p:parameter-set> could be removed from the 
<p:pipeline> context: if you want to share parameter sets, you can 
always create a sequence of <c:parameter> documents to hold them.]

>    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.)

I have a strong preference for using a nested syntax rather than an 
attribute for constructing the parameter set from other parameter sets. 
In other words, rather than:

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

use:

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

and rather than:

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

use:

<p:xslt>
   <p:use-parameter-set name="seta" />
   <p:use-parameter-set name="setb" />
</p:xslt>

The reason is that elsewhere (namely in <p:input>) we use a nested 
syntax for constructing sequences of documents, and this seems to be a 
similar kind of thing. It also simplifies things when it comes to 
figuring out whether parameters in the content or from the used 
parameter sets get priority (see below).

>    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.

I don't much like '#top-level' as a name (sorry). What about 
'#pipeline-parameters'?

>    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.

In the nested syntax that I suggested above, you could manage this by 
altering the order in which the nested <p:parameter> or 
<p:use-parameter-set> elements were specified. For example, to get the 
same effect as above you could do:

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

and:

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

>    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.

I'm OK with this given that <p:parameters> always creates <c:parameter> 
elements with NCNames in the name attribute.

The other thing from my proposal that I'd like to see here is to allow 
extension attributes on the <c:parameter> elements, which are simply 
ignored when a new parameter set is created. It just means that I can 
use documents to hold my parameter sets and not have to worry about 
stripping away any annotations I might place on them.

>    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?
[snip]
> 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>

That should be:

   <p:catch>
     <p:output port="result" />
     <p:identity>
       <p:input port="source"><p:empty /></p:input>
     </p:identity>
   </p:catch>

>     <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>

Cheers,

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

Received on Wednesday, 6 June 2007 19:07:59 UTC