Re: Multiple XSLT Steps with Secondary Outputs

 Thanks Wendell and Norm. I need to look more carefully at Norm's suggestion and also consider Wendell's question about the use of p:identity. I'll get to that sometime later today. Not sure when. But this is all helpful and I appreciate it. Thank you both.
Don
    On Friday, January 24, 2025 at 01:35:03 PM CST, Piez, Wendell A. (Fed) <wendell.piez@nist.gov> wrote:  
 
 Hello again,

On Don's example, I can work Norm's code and I can get the same outputs from smaller simpler logic if I don't bother with exposing the result URIs - what are those p:identity steps doing for us there?

But also I suspect the example is a little artificial since it writes 2a and 2b twice, once each for 1a and 1b. This would make more sense if it were not 2a and 2b, but (for example) 1a2a, 1b2a, 1b2a, 1b2b, i.e., combinatorially, phase 2 emitting multiple results for each separate phase 1.

<p:input port="source" sequence="true">
  <p:inline>
      <doc/>
  </p:inline>
</p:input>

<p:xslt name="create-secondary-documents-1">
  <p:with-input port="stylesheet" href="spec-split-docs-1.xsl"/>
</p:xslt>

<p:for-each name="step1-store">
  <p:with-input pipe="secondary@create-secondary-documents-1"/>
  <p:output port="result" sequence="true" pipe="secondary@create-secondary-documents-2"/>

  <p:store href="{base-uri(/)}" message="store1: {base-uri(/)}"/>
  <p:xslt name="create-secondary-documents-2">
      <p:with-input port="stylesheet" href="spec-split-docs-2.xsl"/>
  </p:xslt>
</p:for-each>

<p:for-each name="step2-store">
  <p:store href="{base-uri(/)}" message="store2: {base-uri(/)}"/>
</p:for-each>

I'm wondering if it wouldn't be easier to replace the xsl:result-document apparatus entirely with XProc - how easy it would be to refactor the XSLT to pull that logic out, would be a different question.

OTOH if you have a lot of xsl:result-document instructions already working for you, it makes sense to know how to use it.

Good problem to think about --

Regards, Wendell

-----Original Message-----
From: Norm Tovey-Walsh <ndw@nwalsh.com>
Sent: Friday, January 24, 2025 12:43 PM
To: Don Smith <dsmith_lockesmith@yahoo.com>
Cc: xproc-dev@w3.org
Subject: Re: Multiple XSLT Steps with Secondary Outputs

Hi Don,

It's a little hard to understand what you want this pipeline to do, so I'm making a few guesses. You didn't say what the stylesheets do. Here's what I invented for testing:

spec-split-docs-1.xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xs"
                version="3.0">

<xsl:output method="xml" encoding="utf-8" indent="no"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="/">
  <xsl:result-document href="split1a.xml"><doc/></xsl:result-document>
  <xsl:result-document href="split1b.xml"><doc/></xsl:result-document>
  <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

spec-split-docs-2.xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xs"
                version="3.0">

<xsl:output method="xml" encoding="utf-8" indent="no"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="/">
  <xsl:result-document href="split2a.xml"><doc/></xsl:result-document>
  <xsl:result-document href="split2b.xml"><doc/></xsl:result-document>
  <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

> <p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0">
>    <p:input port="source"/>
>    <p:output port="result" />
>
>    <p:xslt name="create-secondary-documents-1">
>        <p:with-input port="stylesheet" href="spec-split-docs-1.xsl"/>
>    </p:xslt>

This is going to produce a single document on the result port and a sequenceon the secondary port.

>    <p:for-each name="step1-store">
>        <p:with-input pipe="secondary@create-secondary-documents-1"/>

Okay, we're going to iterate over the secondary documents.

>        <p:store href="{base-uri(/)}"/>

And store them.

>        <p:identity>
>            <p:with-input pipe="result-uri"/>
>        </p:identity>

And output the result URIs.

>    </p:for-each>
>
>    <p:for-each>
>        <p:xslt name="create-secondary-documents-2">
>            <p:with-input port="source"
> pipe="secondary@create-secondary-documents-1"/>

This is going to iterate over each of the output URIs and then call the XSLT step passing all of the documents from the secondary port on
create-secondary-documents-1 each time.

I think that's the only bit that's really confusing.

>            <p:with-input port="stylesheet" href="spec-split-docs-2.xsl"/>
>        </p:xslt>
>    </p:for-each>
>
>    <p:for-each name="step2-store">
>        <p:with-input pipe="secondary@create-secondary-documents-2"/>
>        <p:store href="{base-uri(/)}"/>
>        <p:identity>
>            <p:with-input pipe="result-uri"/>
>        </p:identity>
>    </p:for-each>
>
> </p:declare-step>

Here's my version:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:cx="http://xmlcalabash.com/ns/extensions"
                name="main" version="3.0">

    <p:input port="source"/>
    <p:output port="result" sequence="true"/>

    <p:xslt name="create-secondary-documents-1">
      <p:with-input port="stylesheet" href="spec-split-docs-1.xsl"/>
    </p:xslt>

    <p:for-each name="step1-store">
      <p:with-input pipe="secondary@create-secondary-documents-1"/>
      <p:store href="{base-uri(/)}" message="store1: {base-uri(/)}"/>
      <p:identity>
        <p:with-input pipe="result-uri"/>
      </p:identity>
    </p:for-each>

    <!-- Iterate over each of the secondary documents from the first xslt step. For each one, run the second xslt. The output of this step is all of the documents on the xslt secondary port -->

    <p:for-each>
      <p:with-input pipe="secondary@create-secondary-documents-1"/>
      <p:output port="result" sequence="true"
                pipe="secondary@create-secondary-documents-2"/>
      <p:xslt name="create-secondary-documents-2">
        <p:with-input port="stylesheet" href="spec-split-docs-2.xsl"/>
      </p:xslt>
    </p:for-each>

    <p:for-each name="step2-store">
      <p:store href="{base-uri(/)}" message="store2: {base-uri(/)}"/>
      <p:identity>
        <p:with-input pipe="result-uri"/>
      </p:identity>
    </p:for-each>

</p:declare-step>

Whether it does the "right thing" sort of depends on whether or not I guessed correctly. But hopefully that's useful.

                                        Be seeing you,
                                          norm

--
Norm Tovey-Walsh <ndw@nwalsh.com>
https://norm.tovey-walsh.com/

> I am but a blood, bone, and muscle platform that holds up the camera.
> The pictures take themselves.--James Tallon


  

Received on Monday, 27 January 2025 13:54:26 UTC