XSLT复制具有属性的父元素并更改子元素

时间:2020-09-26 11:33:59

标签: xslt

这张HTML表

<tr>
  <td>
    <p>only one cell without break</p>
  </td>
  <td colspan="3">
    <p>text 1</p>
    <p>text 2</p>
    <p>text 3</p>
  </td>
  <td colspan="3">
    <list>
      <list-item>
        <p>list item 1</p>
      </list-item>
      <list-item>
        <p>list item 2</p>
      </list-item>
      <list-item>
        <p>list item 3</p>
      </list-item>
    </list>
  </td>
</tr>

必须翻译为:

<tr>
  <td>
    only one cell without break
  </td>
  <td colspan="3">
    text 1<break/>
    text 2<break/>
    text 3
  </td>
  <td colspan="3">
    <list>
      <list-item>
        <p>list item 1</p>
      </list-item>
      <list-item>
        <p>list item 2</p>
      </list-item>
      <list-item>
        <p>list item 3</p>
      </list-item>
    </list>
  </td>
</tr>

我正在使用这段XSLT代码:

  <xsl:template match="td">
    <td>
      <xsl:for-each select="p">
        <xsl:apply-templates/> 
        <xsl:if test="position() != last()">
          <break/>
        </xsl:if>
      </xsl:for-each>
      <xsl:apply-templates select="* except p"/> 
    </td>
  </xsl:template>

我必须选择<td>作为父节点,所以我可以用一个<p>标签将一个单元格中的所有<break/>标签更改为除最后一个元素以外的所有元素,其中最后一个元素不止一个<p>在一个单元格内。在一个单元格内只有一个<p>的情况下,也必须删除<p>标签,但是不需要添加<break/>。所有其他标签(即列表)保持不变。它可以工作,但是此代码使我失去了“ colspan”属性。

出于明显的原因(手动设置<td>),属性colspan并非从父级复制。

是否可以通过某种方式“修复”代码并复制具有所有属性的父<td>元素以某种方式输出表?

1 个答案:

答案 0 :(得分:2)

样本代表的唯一变换是

  <xsl:template match="tr/td/p">
      <x>
          <xsl:apply-templates select="@* | node()"/>
      </x>
  </xsl:template>

其余的可以通过身份转换来处理(例如XSLT 3中的<xsl:mode on-no-match="shallow-copy"/>或XSLT 2或1中的模板拼写)。

问题编辑后,任务完全不同,但在我看来仍可以通过推送样式apply-templates和template matching解决,您需要的两个转换表示为两个模板:

  <xsl:template match="tr/td/p">
      <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match="tr/td/p[not(position() = last())]">
      <xsl:apply-templates/>
      <break/>
  </xsl:template>

其余的将通过身份转换处理。

https://xsltfiddle.liberty-development.net/pNmCztv