I write xslt file using xsl fo to generate pdf document with table. I have xml file with several tags with the same name DataContainer example:
<tns:StructureData>
<tns:DataContainer>
<qwe:Data>
<asd:Name>Data1 1</asd:Name>
<asd:Value>100</asd:Value>
<qwe:Data>
<asd:Name>Data1 Inner 1</asd:Name>
<asd:Value>1000000</asd:Value>
</qwe:Data>
</qwe:Data>
<qwe:Data>
<asd:Name>Data1 2</asd:Name>
<asd:Value>200</asd:Value>
</qwe:Data>
<qwe:Data>
<asd:Name>Data1 3</asd:Name>
<asd:Value>300</asd:Value>
</qwe:Data>
<qwe:Data>
<asd:Name>Data1 4</asd:Name>
<asd:Value>400</asd:Value>
</qwe:Data>
</tns:DataContainer>
<tns:DataContainer>
<qwe:Data>
<asd:Name>Data2 1</asd:Name>
<asd:Value>45</asd:Value>
</qwe:Data>
<qwe:Data>
<asd:Name>Data2 2</asd:Name>
<asd:Value>55</asd:Value>
</qwe:Data>
<qwe:Data>
<asd:Name>Data2 3</asd:Name>
<asd:Value>65</asd:Value>
</qwe:Data>
<qwe:Data>
<asd:Name>Data2 4</asd:Name>
<asd:Value>75</asd:Value>
</qwe:Data>
</tns:DataContainer>
</tns:StructureData>
And I want to produce two tables for both DataContaienr tags like this:
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Data1 1</td>
<td>100</td>
</tr>
<tr>
<td>Data1 Inner 1</td>
<td>1000000</td>
</tr>
<tr>
<td>Data1 2</td>
<td>200</td>
</tr>
<tr>
<td>Data1 3</td>
<td>300</td>
</tr>
<tr>
<td>Data1 4</td>
<td>400</td>
</tr>
</table>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Data2 1</td>
<td>45</td>
</tr>
<tr>
<td>Data2 2</td>
<td>55</td>
</tr>
<tr>
<td>Data2 3</td>
<td>65</td>
</tr>
<tr>
<td>Data2 4</td>
<td>75</td>
</tr>
</table>
I wrote this xslt:
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simpleA4" page-height="30cm" page-width="24cm" margin-top="2cm" margin-bottom="2cm" margin-left="1cm" margin-right="1cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simpleA4">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt" font-family="Arial">
<xsl:apply-templates select="/tns:StructureData/tns:DataContainer"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="/tns:StructureData/tns:DataContainer">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="3cm" />
<fo:table-column column-width="10cm" />
<fo:table-header>
<fo:table-row border-width="1px" border-style="solid">
<fo:table-cell xsl:use-attribute-sets="marginColumnStyle">
<fo:block font-weight="bold">Name</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="marginColumnStyle">
<fo:block font-weight="bold">Value</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="/tns:StructureData/tns:DataContainer//*[contains(name(), 'qwe:')]"/>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="/tns:StructureData/tns:DataContainer//*[contains(name(), 'qwe:')]">
<fo:table-row border-width="1px" border-style="solid">
<fo:table-cell>
<fo:block>
<xsl:value-of select="current()/asd:name"/>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="centerCellStyle">
<fo:block>
<xsl:value-of select="current()/asd:value"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
But I get two tables withs data from two DataContainer tags. Result after execute above xslt file:
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Data1 1</td>
<td>100</td>
</tr>
<tr>
<td>Data1 Inner 1</td>
<td>1000000</td>
</tr>
<tr>
<td>Data1 2</td>
<td>200</td>
</tr>
<tr>
<td>Data1 3</td>
<td>300</td>
</tr>
<tr>
<td>Data1 4</td>
<td>400</td>
</tr>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Data2 1</td>
<td>45</td>
</tr>
<tr>
<td>Data2 2</td>
<td>55</td>
</tr>
<tr>
<td>Data2 3</td>
<td>65</td>
</tr>
<tr>
<td>Data2 4</td>
<td>75</td>
</tr>
</table>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Data1 1</td>
<td>100</td>
</tr>
<tr>
<td>Data1 Inner 1</td>
<td>1000000</td>
</tr>
<tr>
<td>Data1 2</td>
<td>200</td>
</tr>
<tr>
<td>Data1 3</td>
<td>300</td>
</tr>
<tr>
<td>Data1 4</td>
<td>400</td>
</tr>
<tr>
<td>Data2 1</td>
<td>45</td>
</tr>
<tr>
<td>Data2 2</td>
<td>55</td>
</tr>
<tr>
<td>Data2 3</td>
<td>65</td>
</tr>
<tr>
<td>Data2 4</td>
<td>75</td>
</tr>
</table>
How I can get separated table for any DataContainer tag? I try some several ways to achieve this but none resolved my problem.
You probably want to replace this line....
<xsl:apply-templates select="/tns:StructureData/tns:DataContainer//*[contains(name(), 'qwe:')]"/>
With this line....
<xsl:apply-templates select=".//*[contains(name(), 'qwe:')]"/>
Or, better still...
<xsl:apply-templates select=".//qwe:*"/>
In the former case, you are selecting the child elements of all DataContainer
elements in the document, whereas in the latter case, you are only selecting the descendants of the DataContainer
you are currently matching.
As an aside, you don't necessarily need to put the full path to an element in a template match (not unless that element may occur at different levels in the document, and you just want to target one in a given place)
So, this template match...
<xsl:template match="/tns:StructureData/tns:DataContainer">
Could be simplified to just this...
<xsl:template match="tns:DataContainer">
See a simplified version at http://xsltfiddle.liberty-development.net/6r5Gh2L