有什么方法可以将 xpath 用于 filter/process 文字结果元素?

Is there any way to use xpath to filter/process literal result elements?

我正在制作一个样式表,以将类似于 IETF(即 xhtml)tables,但面向列的 tables 转换为 xsl-fo。

第一步是将 标签转换为 标签。 不幸的是,出于某种原因,XSL 1.1 规范的作者没有提供一种方法来自动将所有属性从 传输到相应列中的 table-cells,并且属性(宽度除外)也不会自动应用(在我看来,这真是愚蠢的设计决定——here is one of the Antenna House developers complaining about the same thing in 2001!)。继承也不适用,因为 没有任何子项。

这让我的任务是弄清楚为每列设置了哪些格式属性并将它们手动应用到适当的 table 单元格。但是,如何最好地做到这一点?我的一个想法是将所有 节点放入一个变量中,但是我将如何使用 xpath 来处理这些节点?另一个想法是必须有一种方法可以使用临时结果树来做到这一点,但是从来没有使用过这样的东西并且不知道这是否可能,如果是的话,如何使用临时结果树。我用标签 XSLT 1.0 和 XSLT 2.0 发布这个问题只是为了看看是否 一个答案,但我真的不得不使用 XSLT 1.0 来解决这个问题。

编辑: 有人要求一个具体的例子。源文档片段可能如下所示:

<table>
  <col width="33%" font-weight="bold" border="1pt solid black"/>
  <col width="34%" span="2" color="red" background-color="gray"/>
  <col font-style="italic" align="center" background-color="yellow"/>
  <tr><td>A</td><td>B</td><td>C</td><td>D</td></tr>
  <tr><td>dog</td><td>cat</td><td>mouse</td><td>elephant</td></tr>
  ...
</table>

即一个标准的 xhtml table,除了一些通常使用 style 属性表示的属性。

那么自然翻译就是

<table> -->  <fo:table>
<col/>  -->  <fo:table-column/>
<tr>    -->  <fo:table-row>
<td>    -->  <fo:table-cell>

但是,这有一个问题,即 中的 none 属性会自动应用于相应列中的 table 单元格,除非您明确要求使用 from-table-colum() 函数调用它们(宽度除外 自动应用)。因此,例如,对于 table 的 3rd 列中的 table 单元格,我需要像这样输出 fo:

<fo:table-cell color="from-table-column()" background-color="from-table-column()>

并且对于 4th 列中的 table 单元格,我需要输出

<fo:table-cell font-style="from-table-column()" align="from-table-column()" background-color="from-table-column()>

问题是您如何知道要为特定列中的 table 单元格查找哪些属性?

嗯,对于 XSLT 1.0,包含结果节点的变量是结果树片段,要将其转换为节点集以应用于应用 XPath 或进一步处理节点,您将使用 exsl:node-set 或类似的,例如

<xsl:variable name="v1-rtf">
  <fo:table-column>...</fo:table:column>
</xsl:variable>

<xsl:variable name="v1-ns" xmlns:exsl="http://exslt.org/common" select="exsl:node-set($v1-rtf)"/>

<xsl:apply-templates select="$v1-ns/fo:table-column"/>

XSLT 2.0 的唯一区别是您不需要 exsl:node-set 函数及其转换操作,您可以直接使用带有临时树的任何变量,例如

<xsl:variable name="v1">
  <fo:table-column>...</fo:table:column>
</xsl:variable>

<xsl:apply-templates select="$v1/fo:table-column"/>

警告:我对 XSL-FO 一无所知;这只是供您作为起点的东西。

按照我对您问题的理解,您希望每个 table 单元格都具有与源文档中对应的 col 相同的属性列表。通过查看当前处理的 td 的位置并使用它在相同的相对位置查找 col 可以很容易地实现这一点。但是,由于某些 col 元素具有 span 属性,因此这并不那么容易。

我建议的解决方案是从 "enumerating" 个 col 元素开始,以便它们的数量与列的数量完全相同。有了这个,我们就可以按计划进行了。

以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="columns">
    <xsl:for-each select="/table/col">
        <xsl:call-template name="replicate">
            <xsl:with-param name="n">
                <xsl:choose>
                    <xsl:when test="@span">
                        <xsl:value-of select="@span"/>
                    </xsl:when>
                    <xsl:otherwise>1</xsl:otherwise>
                </xsl:choose>
            </xsl:with-param>
        </xsl:call-template>
    </xsl:for-each>
</xsl:variable>

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

<xsl:template match="tr">
    <fo:table-row>
        <xsl:apply-templates select="td"/>
    </fo:table-row>
</xsl:template>

<xsl:template match="td">
    <xsl:variable name="i" select="position()" />
    <fo:table-cell>
        <xsl:for-each select="exsl:node-set($columns)/col[$i]/@*[not(name()='width' or name()='span')]">
            <xsl:attribute name="{name()}">from-table-column()</xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates/>  
    </fo:table-cell>
</xsl:template>

<xsl:template name="replicate">
    <xsl:param name="n"/>
    <xsl:if test="$n">
        <xsl:copy-of select="."/>
        <xsl:call-template name="replicate">
            <xsl:with-param name="n" select="$n - 1"/>
        </xsl:call-template>        
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

当应用于您的输入示例时,将产生以下 结果

<?xml version="1.0" encoding="utf-8"?>
<fo:table xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:table-row>
      <fo:table-cell font-weight="from-table-column()" border="from-table-column()">A</fo:table-cell>
      <fo:table-cell color="from-table-column()" background-color="from-table-column()">B</fo:table-cell>
      <fo:table-cell color="from-table-column()" background-color="from-table-column()">C</fo:table-cell>
      <fo:table-cell font-style="from-table-column()" align="from-table-column()" background-color="from-table-column()">D</fo:table-cell>
   </fo:table-row>
   <fo:table-row>
      <fo:table-cell font-weight="from-table-column()" border="from-table-column()">dog</fo:table-cell>
      <fo:table-cell color="from-table-column()" background-color="from-table-column()">cat</fo:table-cell>
      <fo:table-cell color="from-table-column()" background-color="from-table-column()">mouse</fo:table-cell>
      <fo:table-cell font-style="from-table-column()" align="from-table-column()" background-color="from-table-column()">elephant</fo:table-cell>
   </fo:table-row>
</fo:table>

这是假设 table 单元格本身没有跨度;否则这可能会变得更加复杂。