为具有相同名称的标签生成带有单独 table 的 pdf
Generate pdf with separate table for tags with the same name
我使用 xsl fo 编写 xslt 文件以生成带有 table 的 pdf 文档。我有 xml 文件,其中包含多个具有相同名称的标签 DataContainer 示例:
<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>
我想为两个 DataContaienr 标签生成两个 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>
</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>
我写了这个 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>
但是我从两个 DataContainer 标签中得到了两个 tables 数据。上面xslt文件执行后的结果:
<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>
如何为任何 DataContainer 标签分离 table?我尝试了几种方法来实现这一点,但 none 解决了我的问题。
您可能想要替换此行....
<xsl:apply-templates select="/tns:StructureData/tns:DataContainer//*[contains(name(), 'qwe:')]"/>
用这条线....
<xsl:apply-templates select=".//*[contains(name(), 'qwe:')]"/>
或者,更好的是...
<xsl:apply-templates select=".//qwe:*"/>
在前一种情况下,您选择了文档中所有 DataContainer
个元素的子元素,而在后一种情况下,您只选择了当前 DataContainer
个元素的后代匹配.
顺便说一句,您不一定需要在模板匹配中放置元素的完整路径(除非该元素可能出现在文档中的不同级别,而您只想在给定位置)
所以,这个模板匹配...
<xsl:template match="/tns:StructureData/tns:DataContainer">
可以简化为这样...
<xsl:template match="tns:DataContainer">
查看简化版本
我使用 xsl fo 编写 xslt 文件以生成带有 table 的 pdf 文档。我有 xml 文件,其中包含多个具有相同名称的标签 DataContainer 示例:
<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>
我想为两个 DataContaienr 标签生成两个 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>
</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>
我写了这个 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>
但是我从两个 DataContainer 标签中得到了两个 tables 数据。上面xslt文件执行后的结果:
<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>
如何为任何 DataContainer 标签分离 table?我尝试了几种方法来实现这一点,但 none 解决了我的问题。
您可能想要替换此行....
<xsl:apply-templates select="/tns:StructureData/tns:DataContainer//*[contains(name(), 'qwe:')]"/>
用这条线....
<xsl:apply-templates select=".//*[contains(name(), 'qwe:')]"/>
或者,更好的是...
<xsl:apply-templates select=".//qwe:*"/>
在前一种情况下,您选择了文档中所有 DataContainer
个元素的子元素,而在后一种情况下,您只选择了当前 DataContainer
个元素的后代匹配.
顺便说一句,您不一定需要在模板匹配中放置元素的完整路径(除非该元素可能出现在文档中的不同级别,而您只想在给定位置)
所以,这个模板匹配...
<xsl:template match="/tns:StructureData/tns:DataContainer">
可以简化为这样...
<xsl:template match="tns:DataContainer">
查看简化版本