speedata / publisher

speedata Publisher - a professional database Publishing system
https://www.speedata.de/
GNU Affero General Public License v3.0
293 stars 36 forks source link

XPath conditional inside a loop #513

Closed pr-apes closed 11 months ago

pr-apes commented 11 months ago

@pgundlach,

this layout generates 10 pages (letter size):

<Layout xmlns="urn:speedata.de:2009/publisher/en"
  xmlns:sd="urn:speedata:2009/publisher/functions/en">

  <Pagetype test="true()" width="8.5in" height="11in"/>

  <Record element="data">
    <Loop select="10" variable="pagenum">
      <PlaceObject column="{sd:pagewidth('sp') * 0.5}sp" row="{sd:pageheight('sp') * 0.5}sp" hreference="center" vreference="middle">
      <Textblock textformat="centered">
        <Paragraph>
          <Value select="$pagenum"/>
        </Paragraph>
      </Textblock>
      </PlaceObject>
      <ClearPage/>
    </Loop>
  </Record>
</Layout>

This layout generates 10 pages (legal size):

<Layout xmlns="urn:speedata.de:2009/publisher/en"
  xmlns:sd="urn:speedata:2009/publisher/functions/en">

  <Pagetype test="true()" width="8.5in" height="14in"/>

  <Record element="data">
    <Loop select="10" variable="pagenum">
      <PlaceObject column="{sd:pagewidth('sp') * 0.5}sp" row="{sd:pageheight('sp') * 0.5}sp" hreference="center" vreference="middle">
      <Textblock textformat="centered">
        <Paragraph>
          <Value select="$pagenum"/>
        </Paragraph>
      </Textblock>
      </PlaceObject>
      <ClearPage/>
    </Loop>
  </Record>
</Layout>

This layout fits in A4 paper size the whole contents of the image (fed with outputs from previous layouts [sp --dummy --jobname result -v pdfdoc=publisher.pdf]):

<Layout xmlns="urn:speedata.de:2009/publisher/en"
  xmlns:sd="urn:speedata:2009/publisher/functions/en">

  <Record element="data">
    <Loop select="sd:number-of-pages($pdfdoc)" variable="pagenum">
      <PlaceObject column="{sd:pagewidth('sp') * 0.5}sp" row="{sd:pageheight('sp') * 0.5}sp" hreference="center" vreference="middle" frame="solid">
        <Image visiblebox="mediabox" file="{$pdfdoc}" page="{$pagenum}"
          width="{if (((sd:pagewidth('sp') div sd:pageheight('sp')) > sd:aspectratio(($pdfdoc, $pagenum, 'mediabox'), 'sp'))) then
                    ((sd:pageheight('sp') * sd:imagewidth(($pdfdoc, $pagenum, 'mediabox'), 'sp')) div sd:imageheight(($pdfdoc, $pagenum, 'mediabox'), 'sp'))
                  else
                    sd:pagewidth('sp')
                  }sp" />
        </PlaceObject>
      <ClearPage/>
    </Loop>
  </Record>
</Layout>

Image width is calculated to fit what it reaches first: either page height or page width.

This works fine, but only as long as pages aren't mixed within the same document, such as in:

<Layout xmlns="urn:speedata.de:2009/publisher/en"
  xmlns:sd="urn:speedata:2009/publisher/functions/en">

  <Pagetype test="sd:even(sd:current-page())" width="8.5in" height="11in"/>
  <Pagetype test="sd:odd(sd:current-page())" width="8.5in" height="14in"/>

  <Record element="data">
    <Loop select="10" variable="pagenum">
      <PlaceObject column="{sd:pagewidth('sp') * 0.5}sp" row="{sd:pageheight('sp') * 0.5}sp" hreference="center" vreference="middle">
      <Textblock textformat="centered">
        <Paragraph>
          <Value select="$pagenum"/>
        </Paragraph>
      </Textblock>
      </PlaceObject>
      <ClearPage/>
    </Loop>
  </Record>
</Layout>

Or with this layout:

<Layout xmlns="urn:speedata.de:2009/publisher/en"
  xmlns:sd="urn:speedata:2009/publisher/functions/en">

  <Pagetype test="sd:odd(sd:current-page())" width="8.5in" height="11in"/>
  <Pagetype test="sd:even(sd:current-page())" width="8.5in" height="14in"/>

  <Record element="data">
    <Loop select="10" variable="pagenum">
      <PlaceObject column="{sd:pagewidth('sp') * 0.5}sp" row="{sd:pageheight('sp') * 0.5}sp" hreference="center" vreference="middle">
      <Textblock textformat="centered">
        <Paragraph>
          <Value select="$pagenum"/>
        </Paragraph>
      </Textblock>
      </PlaceObject>
      <ClearPage/>
    </Loop>
  </Record>
</Layout>

Sorry, but I don't understand what is wrong here.

I mean, width is computed within the loop for each page, but the conditional seems to work only for the first page (applying the same consequence to the rest of the pages in the loop).

Is this a bug or what is wrong in my code?

Many thanks for your help.

pgundlach commented 11 months ago

You must not use double parentheses in the argument of sd:aspect-ratio(). Also, the sp gets ignored.

pgundlach commented 11 months ago

Try this layout:

<Layout xmlns="urn:speedata.de:2009/publisher/en"
    xmlns:sd="urn:speedata:2009/publisher/functions/en">
    <SetVariable variable="pdfdoc" select="'out.pdf'" />

    <Record element="data">
        <Loop select="sd:number-of-pages($pdfdoc)" variable="pagenum">
            <Message select="sd:aspectratio($pdfdoc, $pagenum, 'mediabox')" />
        </Loop>
    </Record>
</Layout>
pr-apes commented 11 months ago

You must not use double parentheses in the argument of sd:aspect-ratio(). Also, the sp gets ignored.

Of course, you are totally right, @pgundlach.

Mixing XPath commands, I forgot that sd:aspectratio() only outputs width divided by height. This is a proportion, only a number, not a length.

This is why measurement units make no sense at all in sd:aspectratio().

Sorry for the noise. Closing the issue myself.

pr-apes commented 11 months ago

Of course, many thanks for your help, @pgundlach.