I was hoping that someone could point me in the correct direction with a concept in XSLT 1.0. I am generating a PDF so the code is a bit long and I thought it would be more appropriate to include only the relevant bits.
I have XML similar to the following skeleton (the full XML has dozens of rows that each contain more than just producer and publication):
<root>
<table>
<row>
<PRODUCER/>
<PUBLICATION_CODE_-_NAME/>
</row>
<row>
<PRODUCER/>
<PUBLICATION_CODE_-_NAME/>
</row>
</table>
</root>
I am currently able to generate a table using XSLT that looks similar to this that contains multiple rows:
| Producer Name | Publication |
----------------------------------
|Producer 1 |Publication A |
|Producer 1 |Publication B |
|Producer 1 |Publication C |
|Producer 2 |Publication D |
|Producer 2 |Publication E |
|Producer 2 |Publication F |
And so on in this fashion.
The main portion of the code that produces this in my XSLT is:
<xsl:template match ="table">
<fo:table>
<fo:table-body font-size="10pt"
font-family="sans-serif"
line-height="10pt"
space-after.optimum="3pt">
<xsl:for-each select="row">
<fo:table-row>
<fo:table-cell width="2.125in"
height="0.2in">
<xsl:choose>
<xsl:apply-templates select="PRODUCER"/>
</xsl:choose>
</fo:table-cell>
<fo:table-cell width="3.25in"
height="0.2in">
<xsl:apply-templates select="PUBLICATION_CODE_-_NAME"/>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="PRODUCER">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
<xsl:template match="PUBLICATION_CODE_-_NAME">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
Now the question arises where I want the output of the table to look more like this as opposed to the table above.
| Producer Name | Publication |
----------------------------------
|Producer 1 |Publication A |
| |Publication B |
| |Publication C |
|Producer 2 |Publication D |
| |Publication E |
| |Publication F |
The way that I am attempting to do this is within this portion of the XSLT
<xsl:template match="PRODUCER">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
At this point, as far as I understand, the context node is PRODUCER. So in order to compare PRODUCER values in previous rows I would need to use something to the effect of ../preceding-sibling in order to find the preceding-sibling of last row (instead of PRODUCER). Additionally, the information is already ordered by producer, so it is only necessary for me to look at the closest preceding-sibling as opposed to all of them.
The code that I am attempted to use to solve this issue is the following:
<xsl:template match="PRODUCER">
<fo:block>
<xsl:if test="not(../preceding-sibling::PRODUCER/@value = self/@value>
<xsl:value-of select="@value"/>
</xsl:if>
</fo:block>
</xsl:template>
I don't know if the syntax is incorrect, or whether this a good way to go about doing this, but any and all input would be greatly appreciated. If there is any other information I can provide that would help clarify or if there are any issues with my question please let me know.
Thank you
It could be done with grouping, it can also be done with preceding-sibling. I would note that you say "dozens" ... I would not worry about using grouping. I ran this sample with 2000 rows, execution is 2.3 seconds (in debugging mode in oXygen with Saxon), 0.1 seconds without debugging. Dozens would take a fraction of a second. I have extended your sample here, including a test for the first occurrence which has no preceding-sibling. You could also combine things a bit but I left this so you can see the different decisions:
Sample XML:
XSL with testing for preceding-sibling, put into a variable to work with and only selecting [1] which is the immediately preceding one:
Output: