使用XSL的XML到HTML表 [英] XML to HTML table using XSL

查看:513
本文介绍了使用XSL的XML到HTML表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个XML文件,我从我的数据库导出,结构如下,
'

I have an XML file that I export from my DB which is structured as below, '

<output>
    <row>
        <Month>October</Month>
        <Location>kansas</Location>
        <bus_name>bus1</bus_name>
        <bus_type>volvo</bus_type>
        <bus_colour>red</bus_colour>
        <bus_count>10</bus_count>
    </row>
    <row>
        <Month>October</Month>
        <Location>kansas</Location>
        <bus_name>bus1</bus_name>
        <bus_type>Volvo</bus_type>
        <bus_colour>green</bus_colour>
        <bus_count>11</bus_count>
    </row>
        <Month>October</Month>
        <Location>kansas</Location>
        <bus_name>bus1</bus_name>
        <bus_type>Merc</bus_type>
        <bus_colour>blue</bus_colour>
        <bus_count>5</bus_count>
    </row>
So on...
</output>

我需要将表格看作下面附带的图像。 XSL和XML文件将定期刷新。单元格将根据总线类型具有相似的颜色。

I need the table to look like the image attached below. The XSL and XML file will be refreshed periodically.The cells will have similar color's based on bus type.

我是XSL的新手,因此很难出现有了解决方案。任何帮助将不胜感激。

I'm new to XSL thus having a really hard time coming up with a solution. Any help would be appreciated.

推荐答案

就像一个不同的方法,也处理相同bus_types的颜色。

演示

Just as a different approach and also handling the colours for the same bus_types.
Demo

<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<table>
    <tr>
        <td colspan="9">ACME BUS SERVICE</td>
    </tr>
    <tr>
        <td colspan="9">
            Month: <xsl:value-of select="//Month"/>
        </td>
    </tr>
    <tr>
        <td>Season</td>
        <td>Location</td>
        <td>Bus Name</td>
        <td colspan="2">RED</td>
        <td colspan="2">GREEN</td>
        <td colspan="2">BLUE</td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td></td>
        <td>Bus Type</td>
        <td>Bus Count</td>
        <td>Bus Type</td>
        <td>Bus Count</td>
        <td>Bus Type</td>
        <td>Bus Count</td>
    </tr>
    <xsl:for-each select="//row[Location[not(preceding::Location/. = .)]]" >
        <xsl:variable name="currentLocation" select="./Location"/>
        <tr>
            <xsl:attribute name="class">
              <xsl:value-of select="$currentLocation"/>
             </xsl:attribute>
            <td>
                <xsl:if test="position()=1">Winter</xsl:if>
            </td>
            <td>
                <xsl:value-of select="$currentLocation"/>
            </td>
            <td>
                <xsl:value-of select="./bus_name"/>
            </td>
            <td>
                <xsl:if test="count(//row[Location= $currentLocation]
                                         [bus_type = //row[Location= $currentLocation]
                                         [bus_colour = 'red']/bus_type]) > 1">
                    <xsl:attribute name="class">color</xsl:attribute>
                </xsl:if>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'red']/bus_type"/>
            </td>
            <td>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'red']/bus_count"/>
            </td>
            <td>
                <xsl:if test="count(//row[Location= $currentLocation]
                                         [bus_type = //row[Location=$currentLocation]  
                                         [bus_colour = 'green']/bus_type]) > 1">
                    <xsl:attribute name="class">color</xsl:attribute>
                </xsl:if>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'green']/bus_type"/>
            </td>
            <td>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'green']/bus_count"/>
            </td>
            <td>
                <xsl:if test="count(//row[Location= $currentLocation]
                                         [bus_type = //row[Location=$currentLocation]  
                                         [bus_colour = 'blue']/bus_type]) > 1">
                    <xsl:attribute name="class">color</xsl:attribute>
                </xsl:if>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'blue']/bus_type"/>
            </td>
            <td>
                <xsl:value-of select="//row[Location= $currentLocation]
                                           [bus_colour = 'blue']/bus_count"/>
            </td>
        </tr>
    </xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>

对于每个位置,该位置都设置为< tr>的类名; ,例如< tr class =kansas> 。每个在某个位置使用多次的总线类型的td都会获得class =color。因此,要显示具有不同颜色的表格,您只需添加CSS,例如 .kansas .color {background-color:blue; } 。如果要基于bus_type显示相同的颜色,只需将xslt中的类名color调整为当前的bus_type。

For every location, the location is set as classname to the <tr>, e.g. <tr class="kansas">. Every td with a bus type that is used more than once at a location gets the class="color". So to display the table with different colors, you can just add CSS like e.g. .kansas .color { background-color: blue; }. In case you want to display the same color based on the bus_type, just adjust the classname "color" in the xslt to the current bus_type.

注意:在链接示例中,我只为Texas添加了一行,以显示XSLT显示多个位置,仅设置第一行的季节,并且如果并非为所有位置提供所有颜色,也可以使用。并且输出不是有效的HTML(没有提供html-,head-,body-tags等)。正如您所提到的,您希望获得HTML输出,您可能已经有一个XSLT生成有效的HTML,您可以在其中调整/包含表格所需的部分。

Note: In the linked example I've only added one row for Texas to show that the XSLT displays multiple locations, only sets the season for the first one, and will also work in case not all colors are provided for a location. And the output is not valid HTML (no html-, head-, body-tags etc provided). As you mentioned you'd like to get HTML ouput, you probably already have an XSLT generating valid HTML where you can adjust/include the part you need for the table.

注释中问题的更新:将< tr> 的类名设置为bus_type的名称(如果是bus_type)在一个位置使用不止一次而不是位置:

Update for the question in the comments: To set the class name for a <tr> to the name of the bus_type (in case a bus_type is used more than once at a location) instead of the location:

在上面的XSLT中更改:

Change this in above XSLT:

<tr>
<xsl:attribute name="class">
   <xsl:value-of select="$currentLocation"/>
</xsl:attribute>

进入

<tr>
<xsl:if test="count(//row[Location=$currentLocation]) >  
              count(//row[Location=$currentLocation]/
                      bus_type[not(. = preceding::bus_type)])">  
    <xsl:attribute name="class">
       <xsl:value-of select="//row[Location=$currentLocation]/
                               bus_type[ . = preceding::bus_type]"/>
    </xsl:attribute>
</xsl:if>

更新演示2

附加说明和问题:OP XML的一个调整是将小写volvo改为Volvo。如果DB的原始导出确实混合了大写和小写的名称,则可以在XSLT中处理这个以小写所有bus_names(以获取唯一值)并将中的值的第一个字母大写为< ; TD> 。最好知道你是否使用XSLT 2.0或XSLT 1.0,因为XSLT 2.0提供了简化某些任务的功能 - 例如2.0提供了一个小写()函数,其中在1.0中使用 translate()可以实现相同的参考 - 作为参考因为你提到你是XSL的新手:如何使用XSLT将字符串转换为大写或小写?

进一步的问题是 - 因为XML示例只是数据库导出的一部分 - 如果每个位置只有一行,或者有可能存在各种行,例如: kansas bus1,堪萨斯公共汽车2等

Additional notes and questions: One adjustment to the OP XML was to change the lowercase "volvo" to "Volvo". In case the original export from DB really mixes upper- and lowercase names, this can be handled in the XSLT to lowercase all bus_names (to get the unique values) and uppercase the first letter for the value in the <td>. Also it would be good to know if you use XSLT 2.0 or XSLT 1.0 as XSLT 2.0 provides functionality to simplify some tasks - e.g. 2.0 provides a lower-case() function where in 1.0 the same can be achieved using translate() - as reference for this as you mentioned you're new to XSL: How can I convert a string to upper- or lower-case with XSLT?
Further question is - as the XML example is only a part of the DB export - if there will be only one row for each location or if it is possible that there are various rows, e.g. kansas bus1, kansas bus2 etc.

更新2 对于评论中的第二个问题:我可以添加(几乎)逐行说明并在完成后发表评论。我假设没有必要覆盖HTML部分,只包括XSLT。与此同时,正如您所说,您是XSLT的新手,可能以下内容可能有用:

for < xsl:template match =/> - https://stackoverflow.com/questions/3127108/xsl-xsltemplate-match

XPath轴的
- http://www.xmlplease.com/轴

b $ b用于某些基础知识,例如 - XSLT文档中的模板以什么顺序执行,它们是否与源XML或缓冲输出匹配?

Update 2 for the second question in the comments: I can add an (almost) line by line explanation and will drop a comment when done. I assume it's not necessary to cover the HTML part but only the XSLT. In the meantime, as you mentioned you're new to XSLT, maybe the following can be of use:
for <xsl:template match="/"> - https://stackoverflow.com/questions/3127108/xsl-xsltemplate-match
for XPath axes - http://www.xmlplease.com/axis
for some basics, e.g. - In what order do templates in an XSLT document execute, and do they match on the source XML or the buffered output?

请注意,应避免使用它们在SO处有扩展评论 - 当帖子下面有太多评论时,会显示一条自动消息,建议转移到聊天。因为您需要20的聊天声誉( https://stackoverflow.com/help/privileges ),这不会是目前可能。

Note that it should be avoided at SO to have extended comments - when there are too many comments below a post, an automated message will be displayed that suggests to move to chat. Because you need a reputation of 20 to chat (https://stackoverflow.com/help/privileges), this won't be possible at the moment.

这篇关于使用XSL的XML到HTML表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆