Convert XML List to HTML Table Using XSL

久未见 提交于 2019-12-13 04:36:37

问题


Hello I was struggling with this for the past days and I could not find a good answer nor solution. I have an XML file with a list of objects like this:

<?xml version="1.0" encoding="UTF-8"?>
<LineItems>
    <TableName>Lines</TableName>
    <TableTerm>Lines</TableTerm>
    <LineItems>
        <Class>A Class</Class>
    </LineItems>
    <LineItems>
        <Number>1234</Number>
    </LineItems>
    <LineItems>
        <Description>G</Description>
    </LineItems>
    <LineItems>
        <Class>B Class</Class>
    </LineItems>
    <LineItems>
        <Number>5678</Number>
    </LineItems>
    <LineItems>
        <Description>F</Description>
    </LineItems>
    <ColumnMetadata>
        <Name>Class</Name>
        <Term>Class</Term>
    </ColumnMetadata>
    <ColumnMetadata>
        <Name>Number</Name>
        <Term>No</Term>
    </ColumnMetadata>
    <ColumnMetadata>
        <Name>Description</Name>
        <Term>Description</Term>
    </ColumnMetadata>
</LineItems>

I am applying the following transformaiton:

<?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>
    <xsl:variable name="columns" select="count(LineItems/ColumnMetadata)" />
    <xsl:variable name="items" select="count(LineItems/LineItems)" />
    <xsl:variable name="rows" select="$items div $columns" />
    <table border="1">
        <thead >
            <tr bgcolor="#9acd32">
                <xsl:for-each select="LineItems/ColumnMetadata">
                    <th style="padding: .3em 0;">
                        <xsl:value-of select="Term" />
                    </th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody style="text-align: center;">
            <xsl:for-each select="(//LineItems)[position()&lt;=$rows]">
            <xsl:variable name="i" select="position() - 1"/>
            <tr>
                <xsl:for-each select="(//*)[position()&lt;=$columns]">
                    <xsl:variable name="j" select="position()+($columns*$i)"/>
                    <td style="padding: .3em 0;">
                        <xsl:value-of select="LineItems/LineItems[$j]" />
                    </td>
                </xsl:for-each>
            </tr>
            </xsl:for-each>
        </tbody>
    </table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Finally the desire output for this case would be:

<table>
  <thead>
    <tr>
      <th>Class</th>
      <th>No</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
        <td>A Class</td>
        <td>1234</td>
        <td>G</td>
    </tr>
    <tr>
        <td>B Class</td>
        <td>5678</td>
        <td>F</td>
    </tr>
  </tbody>
</table>

This case is a case of MxN table, I cna know how many columns from nodes. So, to sumarise:

  • The actual list that have to be transformed as a table is all inside root <LineItems>.
  • I don't know how many items (rows) I am going to get, but I can calculate them dividing amount of <LineItems> nodes ($items) by amount of <ColumnMetadata> nodes ($columns)
  • Nodes like <Class>, <Number> and <Description>, are columns in table, but they can have other names, they are dynamic and can be 5, 6... Many columns.

If I transform above XML with XSL in online tools I only get the header row of the table (and inspecting HTML, I can see 2 rows for 2 items, but empty). If I use Visual Studio transformation tool, I not only get header row, I also get first 2 columns of table (in this example Class values) but not the values in the rest of them. I really don't understand what is going on and why do I get different results using different tools.

Thanks in advance


回答1:


lineitmes folllow a regular pattern.

Then I believe it could be simply:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/LineItems">
    <xsl:variable name="columns" select="count(ColumnMetadata)"/>
    <table border="1">
        <thead >
            <tr>
                <xsl:for-each select="ColumnMetadata">
                    <th>
                        <xsl:value-of select="Term"/>
                    </th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="LineItems[position() mod $columns = 1]">
                <tr>
                    <xsl:for-each select=". | following-sibling::LineItems[position() &lt; $columns]">
                        <td>
                            <xsl:value-of select="*"/>
                        </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each>
        </tbody>
    </table>
</xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/31602404/convert-xml-list-to-html-table-using-xsl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!