寻求使用XSLT将XML转换为HTML树视图的优雅解决方案

时间:2012-05-14 15:34:08

标签: xml xslt

(我已经广泛研究过这个问题,但还没有找到合适的解决方案。)

我正在使用XSLT将一系列XML文件转换为类似“树”的HTML文档,其中元素之间的父子关系通过缩进反映出来。

下面的解决方案运行正常,但它太冗长了,我们还需要添加一些新的 未来架构的元素。

什么是一个很好的通用解决方案,可以满足我们的需求?我在网上看到了递归解决方案,其中使用了“深度”变量并且递增并作为参数传入,并用于驱动缩进级别;这似乎是一种常见的模式,但我无法让它为我工作。

感谢。

所以我的数据文件如下所示:

<document>
  <metadata>
    <version>1.0</version>
    <date>1/1/12</date>
    etc...
  </metadata>
  <trackdata>
    <tracks>
      <track>123</track>
      <track>456</track>
      etc...
  </trackdata>
</document>

和XSLT(注意不同级别的文本缩进的不同值):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="no"/>
    <xsl:template match="@*|node()">
        <xsl:apply-templates select="@*|node()" />
    </xsl:template>

        <xsl:template match="metadata">
            Metadata: <xsl:apply-templates/>
        </xsl:template>

        <xsl:template match="version">
          <div style="text-indent:3em">Version: <xsl:value-of select="text()"/></div>
        </xsl:template>

        <xsl:template match="date">
          <div style="text-indent:3em">Date: <xsl:value-of select="text()"/></div>
        </xsl:template>

        <xsl:template match="trackdata">
          Track Data: <xsl:value-of select="text()"/></div>
        </xsl:template>

        <xsl:template match="tracks">
            <div style="text-indent:3em">Tracks: <xsl:apply-templates/>
        </xsl:template>

        <xsl:template match="track">
          <div style="text-indent:6em">Track: <xsl:value-of select="text()"/></div>
        </xsl:template>

等...

1 个答案:

答案 0 :(得分:2)

尝试创建一个变量来保存text-indent值。像这样:

  <xsl:template match="version">
    <xsl:variable name="vIndent" select="count(ancestor::*) * 3"/>    
    <div style="text-indent:{$vIndent}em">Version: <xsl:value-of select="text()"/></div>
  </xsl:template>

这是另一个完整的使用示例......

XML输入(格式正确)

<document>
  <metadata>
    <version>1.0</version>
    <date>1/1/12</date>
  </metadata>
  <trackdata>
    <tracks>
      <track>123</track>
      <track>456</track>
    </tracks>
  </trackdata>
</document>

XSLT 1.0

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

  <xsl:template match="text()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <html>
      <xsl:apply-templates/>
    </html>
  </xsl:template>

  <xsl:template match="*">
    <xsl:variable name="vIndent" select="count(ancestor::*) * 3"/>
    <div style="text-indent:{$vIndent}em"><xsl:value-of select="name()"/>: <xsl:apply-templates/></div>
  </xsl:template>

  <xsl:template match="document">
    <xsl:apply-templates/>
  </xsl:template>  

</xsl:stylesheet>

原始HTML输出

<html>
   <div style="text-indent:3em">metadata: 
      <div style="text-indent:6em">version: 1.0</div>
      <div style="text-indent:6em">date: 1/1/12</div>
   </div>
   <div style="text-indent:3em">trackdata: 
      <div style="text-indent:6em">tracks: 
         <div style="text-indent:9em">track: 123</div>
         <div style="text-indent:9em">track: 456</div>
      </div>
   </div>
</html>

如果您希望第一个div没有缩进,您可以将变量更改为:

<xsl:variable name="vIndent" select="(count(ancestor::*) * 3) - 3"/>