问题
I have the XML file below for which I'm trying to create a XSLT template to tabulate some nodes. May someone could help me out please.
<Main>
<Document>Doc.1</Document>
<Cini>DDFR</Cini>
<List>
<SubList>
<CdTa>ABC</CdTa>
<NN>XYZ</NN>
<ND>
<RiS>
<RiN>
<NSE14>
<MNRs>
<MRD>
<NR>
<N1>393</N1>
<N2>720</N2>
<SNR>
<NR_i>203</NR_i>
<NR_f>49994</NR_f>
</SNR>
</NR>
</MRD>
<MRD>
<NR>
<N1>687</N1>
<N2>345</N2>
<SNR>
<NR_i>55005</NR_i>
<NR_f>1229996</NR_f>
</SNR>
</NR>
</MRD>
</MNRs>
<GNRs>
<RD>
<NR>
<N1>649</N1>
<N2>111</N2>
<SNR>
<NR_i>55400</NR_i>
<NR_f>877</NR_f>
</SNR>
</NR>
</RD>
</GNRs>
<MSNRs>
<NR>
<N1>748</N1>
<N2>5624</N2>
<SNR>
<NR_i>8746</NR_i>
<NR_f>7773</NR_f>
</SNR>
</NR>
<NR>
<N1>124</N1>
<N2>54</N2>
<SNR>
<NR_i>8847</NR_i>
<NR_f>5526</NR_f>
</SNR>
</NR>
</MSNRs>
</NSE14>
<NSE12>
<MBB>990</MBB>
<MRB>123</MRB>
</NSE12>
<MGE13>
<TBB>849</TBB>
<TRB>113</TRB>
</MGE13>
</RiN>
</RiS>
</ND>
</SubList>
</List>
</Main>
And this XSLT code
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#FFF833">
<th style="text-align:left">MNRs</th>
<th style="text-align:left">GNRs</th>
<th style="text-align:left">MSNRs</th>
</tr>
<tr bgcolor="#9acd32">
<th style="text-align:left">N1</th>
<th style="text-align:left">N2</th>
<th style="text-align:left">NR_i</th>
<th style="text-align:left">NR_f</th>
<th style="text-align:left">N1</th>
<th style="text-align:left">N2</th>
<th style="text-align:left">NR_i</th>
<th style="text-align:left">NR_f</th>
<th style="text-align:left">N1</th>
<th style="text-align:left">N2</th>
<th style="text-align:left">NR_i</th>
<th style="text-align:left">NR_f</th>
</tr>
<xsl:for-each select="//MNRs//NR">
<tr>
<td><xsl:value-of select="N1"/></td>
<td><xsl:value-of select="N2"/></td>
<xsl:for-each select="SNR">
<td><xsl:value-of select="NR_i"/></td>
<td><xsl:value-of select="NR_f"/></td>
</xsl:for-each>
</xsl:for-each>
<xsl:for-each select="//GNRs//NR">
<td><xsl:value-of select="N1"/></td>
<td><xsl:value-of select="N2"/></td>
<xsl:for-each select="SNR">
<td><xsl:value-of select="NR_i"/></td>
<td><xsl:value-of select="NR_f"/></td>
</xsl:for-each>
</xsl:for-each>
<xsl:for-each select="//MSNRs//NR">
<td><xsl:value-of select="N1"/></td>
<td><xsl:value-of select="N2"/></td>
<xsl:for-each select="SNR">
<td><xsl:value-of select="NR_i"/></td>
<td><xsl:value-of select="NR_f"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Whit the current XSLT code I'm getting this output that is not the structure I woul like to obtain since I'm only getting some values. The thing is there are 3 parents nodes with the same children names. The parent nodes are MNRs, GNRs and MSNRs
+------+------+-------+---------+----+----+------+------+----+----+------+------+
| MNRs | GNRs | MSNRs | | | | | | | | | |
+------+------+-------+---------+----+----+------+------+----+----+------+------+
| N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f |
+------+------+-------+---------+----+----+------+------+----+----+------+------+
| 393 | 720 | 203 | 49994 | | | | | | | | |
+------+------+-------+---------+----+----+------+------+----+----+------+------+
| 687 | 345 | 55005 | 1229996 | | | | | | | | |
+------+------+-------+---------+----+----+------+------+----+----+------+------+
And I would like to get this output:
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| MNRs | GNRs | MSNRs |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 393 | 720 | 203 | 49994 | 649 | 111 | 55400 | 877 | 748 | 5624 | 8746 | 7773 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 687 | 345 | 55005 | 1229996 | | | | | 124 | 54 | 8847 | 5526 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
Thanks for any help.
回答1:
This is not at all trivial, esp. in XSLT 1.0. I would suggest you try it this way:
XSL 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1" width="80%">
<!-- header -->
<tr>
<th colspan="4">MNRs</th>
<th colspan="4">GNRs</th>
<th colspan="4">MSNRs</th>
</tr>
<tr>
<!-- MNRs -->
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
<!-- GNRs -->
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
<!-- MSNRs -->
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<!-- data -->
<xsl:call-template name="rows">
<xsl:with-param name="MNRs" select="//MNRs//NR"/>
<xsl:with-param name="GNRs" select="//GNRs//NR"/>
<xsl:with-param name="MSNRs" select="//MSNRs//NR"/>
</xsl:call-template>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="rows">
<xsl:param name="MNRs"/>
<xsl:param name="GNRs"/>
<xsl:param name="MSNRs"/>
<xsl:param name="i" select="1"/>
<xsl:if test="$MNRs[$i] or $GNRs[$i] or $MSNRs[$i]">
<tr>
<!-- MNRs -->
<td>
<xsl:value-of select="$MNRs[$i]/N1"/>
</td>
<td>
<xsl:value-of select="$MNRs[$i]/N2"/>
</td>
<td>
<xsl:value-of select="$MNRs[$i]/SNR/NR_i"/>
</td>
<td>
<xsl:value-of select="$MNRs[$i]/SNR/NR_f"/>
</td>
<!-- GNRs -->
<td>
<xsl:value-of select="$GNRs[$i]/N1"/>
</td>
<td>
<xsl:value-of select="$GNRs[$i]/N2"/>
</td>
<td>
<xsl:value-of select="$GNRs[$i]/SNR/NR_i"/>
</td>
<td>
<xsl:value-of select="$GNRs[$i]/SNR/NR_f"/>
</td>
<!-- MSNRs -->
<td>
<xsl:value-of select="$MSNRs[$i]/N1"/>
</td>
<td>
<xsl:value-of select="$MSNRs[$i]/N2"/>
</td>
<td>
<xsl:value-of select="$MSNRs[$i]/SNR/NR_i"/>
</td>
<td>
<xsl:value-of select="$MSNRs[$i]/SNR/NR_f"/>
</td>
</tr>
<!-- recursive call -->
<xsl:call-template name="rows">
<xsl:with-param name="MNRs" select="$MNRs"/>
<xsl:with-param name="GNRs" select="$GNRs"/>
<xsl:with-param name="MSNRs" select="$MSNRs"/>
<xsl:with-param name="i" select="$i + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When applied to your example input, the result will be:
Result
<html>
<body>
<table border="1" width="80%">
<tr>
<th colspan="4">MNRs</th>
<th colspan="4">GNRs</th>
<th colspan="4">MSNRs</th>
</tr>
<tr>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<tr>
<td>393</td>
<td>720</td>
<td>203</td>
<td>49994</td>
<td>649</td>
<td>111</td>
<td>55400</td>
<td>877</td>
<td>748</td>
<td>5624</td>
<td>8746</td>
<td>7773</td>
</tr>
<tr>
<td>687</td>
<td>345</td>
<td>55005</td>
<td>1229996</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>124</td>
<td>54</td>
<td>8847</td>
<td>5526</td>
</tr>
</table>
</body>
</html>
rendered as:
回答2:
Another option is to generate 3 separate tables and display them side-by-side. This is much simpler - but the result is visually different, and the differences are dependent on the browser being used (I presume this can be solved with more CSS):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="//MNRs | //GNRs | //MSNRs">
<table border="1" width="25%" style="display:inline-block">
<!-- header -->
<tr>
<th colspan="4">
<xsl:value-of select="name()"/>
</th>
</tr>
<tr>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<!-- data -->
<xsl:for-each select=".//NR">
<tr>
<td>
<xsl:value-of select="N1"/>
</td>
<td>
<xsl:value-of select="N2"/>
</td>
<td>
<xsl:value-of select="SNR/NR_i"/>
</td>
<td>
<xsl:value-of select="SNR/NR_f"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
Result
<html>
<body>
<table border="1" width="25%" style="display:inline-block">
<tr><th colspan="4">MNRs</th></tr>
<tr>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<tr>
<td>393</td>
<td>720</td>
<td>203</td>
<td>49994</td>
</tr>
<tr>
<td>687</td>
<td>345</td>
<td>55005</td>
<td>1229996</td>
</tr>
</table>
<table border="1" width="25%" style="display:inline-block">
<tr><th colspan="4">GNRs</th></tr>
<tr>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<tr>
<td>649</td>
<td>111</td>
<td>55400</td>
<td>877</td>
</tr>
</table>
<table border="1" width="25%" style="display:inline-block">
<tr><th colspan="4">MSNRs</th></tr>
<tr>
<th>N1</th>
<th>N2</th>
<th>NR_i</th>
<th>NR_f</th>
</tr>
<tr>
<td>748</td>
<td>5624</td>
<td>8746</td>
<td>7773</td>
</tr>
<tr>
<td>124</td>
<td>54</td>
<td>8847</td>
<td>5526</td>
</tr>
</table>
</body>
</html>
Rendered in Safari:
Rendered in Firefox:
来源:https://stackoverflow.com/questions/56453449/xls-transformation-from-xml-in-particular-table-order