0

I'm trying to generate an xml with the help of xslt templates and I have a tricky thing to do:

I have to generate a certain number of elements that have same tags but with different values inside them. Example of xslt stylesheet:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="NbOfBatches"/>
    <xsl:param name="wholeTag"/>
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <Document xmlns="urn:something" xmlns:file="someUrn>
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="$NbOfBatches"></xsl:value-of></file:NbOfBatches>
                <xsl:call-template name="selects">
                    <xsl:with-param name="i">1</xsl:with-param>
                    <xsl:with-param name="count"><xsl:value-of select="$NbOfBatches"/></xsl:with-param>
                </xsl:call-template>
            </FileAppHdr>
        </Document>
    </xsl:template>

    <xsl:template name="selects">
        <xsl:param name="i" />
        <xsl:param name="count" />

        <xsl:if test="$i &lt;= $count">
            <xsl:call-template name="credit">
                <xsl:with-param name="param0"/>
            </xsl:call-template>
        </xsl:if>

        <xsl:if test="$i &lt;= $count">
            <xsl:call-template name="selects">
                <xsl:with-param name="i">
                    <xsl:value-of select="$i + 1"/>
                </xsl:with-param>
                <xsl:with-param name="count">
                    <xsl:value-of select="$count"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="credit">
        <xsl:param name="param0"/>
        <CreditTransfer>
            <xsl:value-of select="$param0"/>
        </CreditTransfer>
    </xsl:template>
</xsl:stylesheet>

In this way, I can use Saxon or JAXP and call .setParameter() for NbOfBatches, it will generate that number of tags. However is there a way to generate / modify name of param0 inside CreditTransfer so that I can loop through data in Java and use .setParameter("param1", value1) and so on ?

Thank you

Priku
  • 1
  • To me it seems like you want to pass in a sequence of atomic values, that should be easy, at least using s9api. Then you process the sequence using `xsl:iterate` or `xsl:for-each` or even using `xsl:apply-templates` and create the `CreditTransfer` element with the value of each item in the sequence. – Martin Honnen Oct 20 '22 at 14:05
  • Hi @MartinHonnen ! Thanks a lot for your answer and patience with my beginner xslt skills. Quick follow-up: Would it be more complex if I had to pass a list of params ? for each CreditTransfer tag I have to set a couple of values (all strings, let's say) ? – Priku Oct 20 '22 at 14:19
  • I would think that you can in that case pass in a sequence of maps and process each map. So on the Java side you would create a parameter value that is a sequence of maps and the code would continue to process the sequence with e.g. `xsl:iterate` or `xsl:for-each` or even `xsl:apply-templates`, only then it would create e.g. `{?amount}{?currency}`, i.e. populate some XML from some map values. – Martin Honnen Oct 20 '22 at 14:34

1 Answers1

1

Rather than trying to pass structured data as a stylesheet parameter, why not generate that structured data as XML and pass that XML document as the source document of the transformation?

As an example, imagine a source XML document with param0 in each Batch:

<Batches>
  <Batch>
    <param0>it was the best of times</param0>
  </Batch>
  <Batch>
    <param0>it was the worst of times</param0>
  </Batch>
  <Batch>
    <param0>it was the age of wisdom</param0>
  </Batch>
  <Batch>
    <param0>it was the age of foolishness</param0>
  </Batch>
</Batches>

with a simplified version of your stylesheet:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <Document xmlns:file="someUrn">
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="count(//Batch)"/></file:NbOfBatches>
                <xsl:for-each select="//Batch">
                  <xsl:call-template name="selects">
                      <xsl:with-param name="param0" select="param0" />
                  </xsl:call-template>                  
                </xsl:for-each>
            </FileAppHdr>
        </Document>
    </xsl:template>

    <xsl:template name="selects">
        <xsl:param name="param0" />

        <xsl:call-template name="credit">
            <xsl:with-param name="param0" select="$param0" />
        </xsl:call-template>

    </xsl:template>

    <xsl:template name="credit">
        <xsl:param name="param0"/>
        <CreditTransfer>
            <xsl:value-of select="$param0"/>
        </CreditTransfer>
    </xsl:template>
</xsl:stylesheet>

produces this output:

<Document xmlns:file="someUrn">
   <FileAppHdr>
      <file:NbOfBatches>4</file:NbOfBatches>
      <CreditTransfer>it was the best of times</CreditTransfer>
      <CreditTransfer>it was the worst of times</CreditTransfer>
      <CreditTransfer>it was the age of wisdom</CreditTransfer>
      <CreditTransfer>it was the age of foolishness</CreditTransfer>
   </FileAppHdr>
</Document>

It's fairly trivial to generate XML from structured data in Java using the Saxon sapling classes. https://www.saxonica.com/html/documentation10/javadoc/net/sf/saxon/sapling/package-summary.html

al.truisme
  • 450
  • 2
  • 11