XSLT使用子元素名称作为表头

时间:2014-01-16 12:35:22

标签: xml xslt xpath xslt-1.0 xalan

我是xsl中的新手,我有一些结构相似的xml文件,如下所示:

 <catalog>
        <cd>
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <country>USA</country>
            <company>Columbia</company>
            <price>10.90</price>
            <year>1985</year>
        </cd>
        <cd>
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
    </catalog>

和其他类似但有歌曲的标题和数量的歌曲描述

<catalog>
    <cd>
        <title>Eros</title>
        <number_of_songs>12</number_of_songs>
    </cd>
    <cd>
        <title>One</title>
        <number_of_songs>12</number_of_songs>
    </cd>
</catalog>

我需要的是为所有xml创建一个xsl文件,创建一个表并获取cd的子元素的名称,将它们作为每个cd和一行描述。 像这样:

║标题║歌曲数量

║爱神║12

║一个║12

无法发布图片:(

到目前为止,我已经完成了这个:

<?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 style="border:2px solid #24343A; border-radius: 4px;">
                    <tr bgcolor="#4488A5" style="color:#ffffff; text-align:center;">

                        <xsl:for-each select="catalog/cd/child::*">
                            <th> <xsl:value-of select ="local-name()"/></th>
                        </xsl:for-each>
                    </tr>
                    <xsl:for-each select="catalog/cd">
                        <tr bgcolor="#8DC1D7" style="color:#21323B;">
                            <xsl:for-each select="child::*">
                                <td> <xsl:value-of select ="child::*"/></td>
                            </xsl:for-each>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

但它不起作用,我得到了标题,但它重复了很多次,并且无法获得价值 感谢

2 个答案:

答案 0 :(得分:2)

使用下面的样式表。我也建议你仔细研究它。

请注意

  • 每当不合适时,您应该避免使用xsl:for-each。相反,请使用appyl-templates并编写与相关元素匹配的单独模板。
  • 目前尚不清楚是否要转换显示的第一个XML文件。为了达到您的输出,不需要它。
  • local-name()仅在元素具有名称空间的情况下才有意义。要简单地检索元素的名称,请使用name()

编辑修改后的样式表,由@Tomalak建议。

<强>样式表

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:strip-space elements="*"/>

 <xsl:template match="/catalog">
    <html>
        <body>
            <table style="border:2px solid #24343A; border-radius: 4px;">
              <tr>
                 <th>Title</th>
                 <th>Number of songs</th>
              </tr>
              <xsl:apply-templates/>
            </table>
        </body>
    </html>
 </xsl:template>

 <xsl:template match="cd">
  <tr bgcolor="#4488A5" style="color:#ffffff; text-align:center;">
     <xsl:apply-templates select="title|number_of_songs" />
  </tr>
 </xsl:template>

 <xsl:template match="title|number_of_songs">
  <td>
     <xsl:value-of select="."/>
  </td>
 </xsl:template>

</xsl:stylesheet>

<强>输出

<html>
 <body>
  <table style="border:2px solid #24343A; border-radius: 4px;">
     <tr>
        <th>Title</th>
        <th>Number of songs</th>
     </tr>
     <tr bgcolor="#4488A5" style="color:#ffffff; text-align:center;">
        <td>Eros</td>
        <td>12</td>
     </tr>
     <tr bgcolor="#4488A5" style="color:#ffffff; text-align:center;">
        <td>One</td>
        <td>12</td>
     </tr>
  </table>
 </body>
</html>

Firefox中的输出

enter image description here


可能的增强功能

您尝试过的XSLT从XML文件中检索标题列的名称。这是一种正确的方法:

 <tr>
   <th>
      <xsl:value-of select="name(cd[1]/title)"/>
   </th>
   <th>
      <xsl:value-of select="name(cd[1]/number_of_songs)"/>
   </th>
 </tr>

但是,这会复制元素的确切名称。因此,在HTML中,您的列标题将是小写的,第二个将如下所示:number_of_songs

答案 1 :(得分:1)

你离我不远。两件事:

  • 您不希望标题重复 - 您只需要第一张CD的元素名称,因此第一个表达式变为catalog/cd[1]/*(child :: *可以替换为*)
  • 您想要每个值的文本内容,而不是子元素。所以使用text()而不是child :: *

见下文:

<?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 style="border:2px solid #24343A; border-radius: 4px;">
                    <tr bgcolor="#4488A5" style="color:#ffffff; text-align:center;">
                        <xsl:for-each select="catalog/cd[1]/*">
                            <th> <xsl:value-of select ="local-name()"/></th>
                        </xsl:for-each>
                    </tr>
                    <xsl:for-each select="catalog/cd">
                        <tr bgcolor="#8DC1D7" style="color:#21323B;">
                            <xsl:for-each select="*">
                                <td> <xsl:value-of select="text()"/></td>
                            </xsl:for-each>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>