- From: Geert Josten <geert.josten@daidalos.nl>
- Date: Wed, 12 Oct 2011 15:39:17 +0200
- To: Matthieu Ricaud-Dussarget <matthieu.ricaud@igs-cp.fr>, "xproc-dev@w3.org" <xproc-dev@w3.org>
Hi Matthieu, If you are not explicit about input/output bindings, the following step takes the primary output of the previous as primary input, if there is any. In your case the p:choose is expecting a primary output on the p:store, because you are not being explicit, and there isn't any. Not sure I understood correctly what you write below, but it sounds like you want to reroute the output of the p:xslt above the p:store to the first next input after the p:store. You could take all alternatives of the following choose and add in each of the first steps an explicit input binding, something like this: <p:xslt ... name="xslt"/> <p:store .../> ... <p:error ...> <p:input port="source"> <p:pipe step="xslt" port="result"/> </p:input> </p:error> Another option, which is most often easier, is to put a p:identity with such an input binding after p:store: <p:xslt ... name="xslt"/> <p:store .../> <p:identity> <p:input port="source"> <p:pipe step="xslt" port="result"/> </p:input> </p:identity> ... <p:error .../> But since this is a common case, it is worthwhile to declare a helper step to do that. I wrote the following, which combines a p:store with such input rerouting, together with a p:choose so the p:store is only done if a debug parameter was passed through.. <!--+========================================================+ | Step log | | Write debug xml based on debug parameter. +--> <p:declare-step type="ut:log" name="current"> <p:input port="source" sequence="true"/> <p:input port="parameters" kind="parameter"/> <p:output port="result" sequence="true"> <!-- pipe input straight through to output --> <p:pipe step="current" port="source"/> </p:output> <p:option name="href" required="true"/> <p:option name="method" select="'xml'"/> <p:option name="indent" select="'true'"/> <!-- clean up parameters port input to stop p:variable from complaining --> <ut:parameters name="params"/> <p:group> <p:variable name="debug" select="(//c:param[@name='debug']/@value, false())[1]"><p:pipe step="params" port="parameters"/></p:variable> <p:choose> <p:when test="string($debug) eq 'true'"> <p:wrap-sequence wrapper="sequence"/> <ut:message> <p:with-option name="message" select="concat('Logging to ', $href)" /> </ut:message> <p:store> <p:with-option name="href" select="$href"/> <p:with-option name="method" select="$method"/> <p:with-option name="indent" select="$indent"/> </p:store> </p:when> <p:otherwise> <p:sink/> </p:otherwise> </p:choose> </p:group> </p:declare-step> (might give you some ideas..) Kind regards, Geert -----Oorspronkelijk bericht----- Van: xproc-dev-request@w3.org [mailto:xproc-dev-request@w3.org] Namens Matthieu Ricaud-Dussarget Verzonden: woensdag 12 oktober 2011 15:26 Aan: xproc-dev@w3.org Onderwerp: Re: New to Xproc Question : conditionnal "output port" definition? Hi Geert, Hi Norm, This was my first post on this list and I'm happy to see how responsive it is ! Thanks a lot for your both instructive answers ! You save me from "sinking" with xproc ;-) I added a <p:sink> step after <p:error> and it works. But.... I actually get a new error with the xpath test : GRAVE: It is a dynamic error if the select expression makes reference to the context node, size, or position when the context item is undefined. This has to do with what was before the <p:choose> step : <p:xslt> <p:store> When I comment the <p:store> it works! I guess this is because <p:xslt> result port is primary whereas <p:store> is not. How can I store the result at any step (for debugging) and "continue" ? What I don't understand is that this sequence of steps works fine (that's what I had before adding the <p:choose>) : <p:xslt> source (primary), result (primary) <p:store> source (primary) result (not primary) <p:xslt> source (primary), result (primary) The result of the first xslt is indeed feeding the 2nd xslt, even with p:store inbetween. p:store has no output, so how is it bind to the 2nd xslt ? whereas : <p:xslt> <p:store> <p:choose> <p:when><p:error></p:when> <p:otherwise><p:xslt></p:otherwise> </p:choose> doesn't work (no context node) If I'm able to apply an xslt after <p:store> doesn't it mean that there is a context node btw an xml output ? Hmm still lost but still investigate, any tips ? Thanks Matthieu. My whole code <?xml version="1.0"?> <p:declare-step xmlns:p="http://www.w3.org/ns/xproc" xmlns:c="http://www.w3.org/ns/xproc-step" xmlns:ecf="http://www.igs-cp.fr/ecf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf" xmlns:igs="http://www.igs-cp.fr" version="1.0" name="epubFixedProcess"> <p:input port="config" primary="true"> <p:document href="config.xml"/> </p:input> <p:output port="result"> <p:empty/><!--Since we are writing to files with p:store, set the output to empty.--> </p:output> <p:pack name="aggregate" wrapper="aggregate" wrapper-namespace="http://www.igs-cp.fr" wrapper-prefix="igs"> <p:input port="alternate"> <p:document href="PAGES_SVG_0/pages.xml"></p:document> </p:input> </p:pack> <p:xslt name="add-viewport"> <p:input port="source"> <p:pipe step="aggregate" port="result"></p:pipe> </p:input> <p:input port="stylesheet"> <p:document href="../xslt/add-viewport.xsl"/> </p:input> <p:input port="parameters"><p:empty/></p:input> </p:xslt> <p:store href="_debug/aggregate.xml" encoding="UTF-8" omit-xml-declaration="false" indent="true" name="store_aggregate"/> <p:choose name="stop_if_viewport_inconsistence"> <p:when test="count(distinct-values(/igs:aggregate/doc/pages/page/@viewportX))!=1"> <p:error name="viewport_err" code="viewport_err"> <p:input port="source"> <p:inline> <message>Les viewports ne sont pas homogènes!</message> </p:inline> </p:input> </p:error> <p:sink/> <!--cf. http://markmail.org/thread/chtq5xepgoul5g4k--> </p:when> <p:otherwise> <p:xslt name="generateECF"> <p:input port="source"> <p:pipe step="add-viewport" port="result"></p:pipe> </p:input> <p:input port="stylesheet"> <p:document href="../xslt/generateECF.xsl"/> </p:input> <p:input port="parameters"><p:empty/></p:input> </p:xslt> <p:store encoding="UTF-8" omit-xml-declaration="false" indent="true"> <p:with-option name="href" select="concat(/ecf:content/opf:metadata/dc:identifier[@id=parent::opf:metadata/@unique-identifier],'.ecf')"></p:with-option> </p:store> </p:otherwise> </p:choose> </p:declare-step> Le 12/10/2011 12:59, Norman Walsh a écrit : > Matthieu Ricaud-Dussarget<matthieu.ricaud@igs-cp.fr> writes: >> Actually Calabash raises this error : >> GRAVE: It is a static error if two subpipelines in a p:choose declare >> different outputs. > This is one of the inconvenient corners in XProc. You have to arrange for all > the branches of a p:choose (and a p:try/p:catch) to produce the same outputs. > > You've also hit another corner case. > > The WG decided that the most common case for a p:choose was one where > each branch produced a single output. In that case, putting in a > p:error branch was inconvenient because it didn't produce any output, > so you had to put some sort of a dummy step after it in order to make > sure that that branch conformed to the rule. But because that step > wasn't going to have any data-flow connection to the p:error, you also > had to wire it up explicitly. All of this was terribly inconvenient. > > So the WG decided to give p:error a primary output port. Nothing will > ever appear on it, but it satisfies the rule about consistent outputs. > > Except, in your case, the other branch *doesn't* produce any output. > > Sigh. > > Maybe we should have increased the burden on implementors instead and > stated that any branch that must end in a p:error doesn't count. But > we didn't. > > Here's the fix: > >> <p:choose name="stop_if_viewport_inconsistence"> >> <p:when >> test="count(distinct-values(/igs:aggregate/doc/pages/page/@viewportX))!=1"> >> <p:error name="viewport_err" code="viewport_err"> >> <p:input port="source"> >> <p:inline> >> <message>viewports inconsistence here !</message> >> </p:inline> >> </p:input> >> </p:error> > <p:sink/> > >> </p:when> >> <p:otherwise> >> <p:xslt name="generateECF"> >> <p:input port="source"> >> <p:pipe step="add-viewport" port="result"></p:pipe> >> </p:input> >> <p:input port="stylesheet"> >> <p:document href="../xslt/generateECF.xsl"/> >> </p:input> >> <p:input port="parameters"><p:empty/></p:input> >> </p:xslt> >> <p:store encoding="UTF-8" omit-xml-declaration="false" indent="true"> >> <p:with-option name="href" >> select="concat(/ecf:content/opf:metadata/dc:identifier[@id=parent::opf:metadata/@unique-identifier],'.ecf')"></p:with-option> >> </p:store> >> </p:otherwise> >> </p:choose> > That p:sink consumes the output of p:error and as a result, neither > branch has a primary output port and so the rules for p:choose are > satisfied. > > BTW, you don't need to say: > > <p:output port="result"> > <p:empty/> > </p:output> > > If you're pipeline doesn't have any output, simply don't declare any output ports. > > Be seeing you, > norm > -- Matthieu Ricaud IGS-CP Service Livre numérique
Received on Wednesday, 12 October 2011 13:40:01 UTC