XSL 模板 - 需要帮助从行中获取 class 名称

XSL template - need help getting class name from row

我有一个测试html表:

<table>
  <tr>
    <th style="width:10px;" />
    <th style="width:80px;">Name</th>
    <th style="width:350px;">Number</th>
    <th style="width:80px;">Date<br />2014-12-31</th>
  </tr>
  <tr class="parent" data-level="0">
    <td />
    <td class="Center">123-12345</td>
    <td>     Range</td>
    <td class="Number">
      <br />
    </td>
  </tr>
  <tr class="child" >
    <td>
      <div class="childNo"  />
    </td>
    <td class="Center">D</td>
    <td>     Test Description</td>
    <td class="Number">123456<br /></td>
  </tr>

</table>

我只想检查 <TR> class 是否为 "parent",如果是,则将 "expando" 连接到 class。所以它看起来像这样:

<table>
  <tr>
    <th style="width:10px;" />
    <th style="width:80px;">Name</th>
    <th style="width:350px;">Number</th>
    <th style="width:80px;">Date<br />2014-12-31</th>
  </tr>
  <tr class="parent expando" data-level="0">
   ....

我似乎无法使用 xsl 执行此操作。我不确定是否需要使用模板匹配。

如有任何帮助,我们将不胜感激。

提前致谢。

您可以复制整个 table,然后只将 class 添加到所有具有 class="parent"tr,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
 <xsl:output method="html" doctype-public="XSLT-compat" 
    omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
 <xsl:strip-space elements="*"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
  </xsl:template>
  <xsl:template match="tr[@class='parent']">
    <xsl:copy>
      <xsl:attribute name="class" select="'parent expando'"/>
      <xsl:attribute name="data-level" select="@data-level"/>
        <xsl:apply-templates select="td"/>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

输出:

<table>
  <tr>
    <th style="width:10px;"></th>
    <th style="width:80px;">Name</th>
    <th style="width:350px;">Number</th>
    <th style="width:80px;">Date<br>2014-12-31
    </th>
  </tr>
  <tr class="parent expando" data-level="0">
    <td></td>
    <td class="Center">123-12345</td>
    <td>     Range</td>
    <td class="Number"><br></td>
  </tr>
  <tr class="child">
    <td>
      <div class="childNo"></div>
    </td>
    <td class="Center">D</td>
    <td>     Test Description</td>
    <td class="Number">123456<br></td>
  </tr>
</table>

具有匹配模式的模板<xsl:template match="tr[@class='parent']"> 使用

匹配所有具有 class parenttr
<xsl:copy>
   <xsl:attribute name="class" select="'parent expando'"/>
   <xsl:attribute name="data-level" select="@data-level"/>
     <xsl:apply-templates select="td"/>
</xsl:copy>

复制整个 tr 并将属性 class 的值更改为两个 classes.

更新: 作为附加要求,这也适用于 tr,它可以有额外的 classes 以及 class parent.
以下调整处理此问题:

<xsl:template match="tr[contains(@class,'parent')]">
    <xsl:copy>
            <xsl:attribute name="class" select="concat(@class, ' expando')"/>
            <xsl:attribute name="data-level" select="@data-level"/>
        <xsl:apply-templates select="td"/>
    </xsl:copy>
</xsl:template>

现在所有包含 class parenttr 都将被匹配,并且作为 class 属性的新值 class expando 将添加到当前 class 值:

<xsl:attribute name="class" select="concat(@class, ' expando')"/>

更新: 正如评论所注意到的,这不是 <xsl:attribute> 的有效 XSLT 1.0 语法 - 它应该是

<xsl:attribute name="class">
  <xsl:value-of select="concat(@class, ' expando')"/>
</xsl:attribute>
<xsl:attribute name="data-level">
  <xsl:value-of select="@data-level"/>
</xsl:attribute>

这是使用在线 XSLT 处理器进行测试的,尽管 XSLT 之前被声明为 1.0,但它没有抛出任何错误。如评论中所述,使用 XSLT 2.0 处理器 (Saxon 9.5.1.6) 只是我的错误,在在线版本中,它不会将所有错误和警告传递给用户。切换到 XSLT 1.0 处理器 (Saxon 6.5) 会导致正确的错误 Attribute select is not allowed on this element

虽然这是公认的答案,但我认为 Lingamurthy CS 给出的答案是 better/cleaner 方法,因为它只更改了必要的 class 属性。我早该知道省点不必要的 xsl:copy.

您可以使用以下样式表,它有两个模板。首先,一个身份模板用于复制源文档中的所有节点。其次,仅更新父级为 tr@class 和值为“父级”的值,因此无需担心 tr 元素或其其他属性:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">
    <xsl:output 
        method="html" doctype-public="XSLT-compat" 
        omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="tr/@class[contains(., 'parent')]">
        <xsl:copy>
            <xsl:value-of select="concat(., ' expando')"/>
        </xsl:copy>
    </xsl:template>

</xsl:transform>