使用xslt转换嵌套的子节点

时间:2012-09-11 09:06:59

标签: xml xslt xpath

XML数据文件

<?xml version="1.0" encoding="utf-8"?>
<page>
    <tab dim="70">

        <tab dim="50">
        alpha

        </tab>
        <tab dim="50">
        alpha

        </tab>

    </tab>
    <tab dim="30">
        gama
    </tab>
</page>

XSLT文件

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

<xsl:output method="xml" version="1.0"
encoding="iso-8859-1" indent="yes"/>

<xsl:template match="/">
    <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
    <html>
    <head>
        <title>Title</title>
        <link type="text/css" href="/css/framework.css" rel="stylesheet"/>

    </head>
    <body>
    <div id="page-base">
        <xsl:for-each select="//tab">
        <div class="wrapper tab">
            <xsl:attribute name="style"> 
                width:<xsl:value-of select="@dim" />%;
                min-width:<xsl:value-of select="@dim" />%;
                max-width:<xsl:value-of select="@dim" />%;
            </xsl:attribute>
            <xsl:value-of select="." />
        </div>
        </xsl:for-each>
    </div>
    </body>
    </html>
</xsl:template>

</xsl:stylesheet>

输出继电器

<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<link rel="stylesheet" href="/css/framework.css" type="text/css">
</head>
<body>
<div id="page-base">
 <div class="wrapper tab" style=" width:70%; min-width:70%; max-width:70%; ">
   alpha alpha   
 </div>
 <div class="wrapper tab" style=" width:50%; min-width:50%; max-width:50%; "> alpha </div>
 <div class="wrapper tab" style=" width:50%; min-width:50%; max-width:50%; "> alpha </div>
 <div class="wrapper tab" style=" width:30%; min-width:30%; max-width:30%; "> gama </div>
</div>
</body>

所需的输出

<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<link rel="stylesheet" href="/css/framework.css" type="text/css">
</head>
<body>
<div id="page-base">
 <div class="wrapper tab" style=" width:70%; min-width:70%; max-width:70%; ">
  <div class="wrapper tab" style=" width:50%; min-width:50%; max-width:50%; "> alpha </div>
  <div class="wrapper tab" style=" width:50%; min-width:50%; max-width:50%; "> alpha </div>
 </div>
 <div class="wrapper tab" style=" width:30%; min-width:30%; max-width:30%; "> gama </div>
</div>
</body>
</html>

1 个答案:

答案 0 :(得分:3)

关键是根本不使用<xsl:for-each>。改为使用模板匹配。

<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="/">
    <html>
      <head>
        <title>Title</title>
        <link type="text/css" href="/css/framework.css" rel="stylesheet"/>
      </head>
      <body>
        <xsl:apply-templates />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="page">
    <div id="page-base">
      <xsl:apply-templates />
    </div>
  </xsl:template>

  <xsl:template match="tab">
    <div class="wrapper tab" style="width:{@dim}%; min-width:{@dim}%; max-width:{@dim}%;">
      <xsl:apply-templates />
    </div>
  </xsl:template>
</xsl:stylesheet>

结果:(另见http://xsltransform.net/gWmuiK6

<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Title</title>
      <link type="text/css" href="/css/framework.css" rel="stylesheet">
   </head>
   <body>
      <div id="page-base">
         <div class="wrapper tab" style="width:70%; min-width:70%; max-width:70%;">
            <div class="wrapper tab" style="width:50%; min-width:50%; max-width:50%;">
               alpha


            </div>
            <div class="wrapper tab" style="width:50%; min-width:50%; max-width:50%;">
               alpha


            </div>
         </div>
         <div class="wrapper tab" style="width:30%; min-width:30%; max-width:30%;">
            gama

         </div>
      </div>
   </body>
</html>

要摆脱输出中的空白区域,您只需要添加另一个模板:

<xsl:template match="tab/text()">
  <xsl:value-of select="normalize-space()" />
</xsl:template>

有些特定情况<xsl:for-each>是正确的选择。这不是其中的一个。

每当你倾向于使用<xsl:for-each>时,你应该停下来思考。在绝大多数情况下<xsl:apply-templates>是你真正想要的。

仅当您发现 <xsl:for-each>的令人信服的理由时才使用<xsl:apply-templates>。如果你想不出这样的原因,那么可能没有。


要输出显示在输入中的节点而不更改它们,请添加标识模板:

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

要将输出中不需要的节点静音,请添加一个空模板:

<xsl:template match="node/to/match" />