xml - 使用xslt转换嵌套的子节点

标签 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>

最佳答案

关键是根本不使用<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" />

关于xml - 使用xslt转换嵌套的子节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12366298/

相关文章:

python - 如何创建 RML 报告?

xml - 在 xml 层次结构中向上移动分隔符元素

php - 使用 PHP SimpleXML 选择具有特定名称的所有节点 - 附上源代码

XPath 条件返回 "wrong"节点

android - 复合布局是否总是需要自己的类?

php - S3 URL 中带双引号的文件名会导致参数无效

xml - 如何使用 XPath 和 XSLT 处理一组兄弟节点并根据其中两个兄弟节点处理特定的兄弟节点子集

xslt - 仅通过 XPath 计算特定子项的数量

java - fragment 中的维基图像识别

java - 从项目目录而不是原始目录应用的相对文件路径