简体   繁体   English

有什么方法可以使用xpath过滤/处理文字结果元素?

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

I'm working on a stylesheet to transform tables similar to IETF (ie xhtml) tables, but column-oriented, to xsl-fo. 我正在处理一个样式表,以将类似于IETF(即xhtml)表但面向列的表转换为xsl-fo。

One of the first steps is to transform <col/> tags to <fo:table-column/> tags. 第一步之一是将<col />标记转换为<fo:table-column />标记。 Unfortunately for some reason the authors of the XSL 1.1 spec didn't provide a way to transfer all attributes automatically from <fo:table-column/> to the table-cells in the corresponding column, and the attributes (with the exception of width) don't apply automatically, either (really dumb design decision, in my opinion -- here is one of the Antenna House developers complaining about the same thing in 2001! ). 不幸的是,由于某些原因,XSL 1.1规范的作者没有提供将所有属性自动从<fo:table-column />转移到相应列中的表格单元以及属性(宽度除外)的方法。 ),也不会自动应用(我认为这确实是愚蠢的设计决定- 这是天线之家的一位开发商在2001年抱怨同一件事! )。 Inheritance doesn't apply, either, as <fo:table-column/> doesn't have any children. 继承也不适用,因为<fo:table-column />没有任何子代。

This leaves me with the task of figuring out what formatting attributes have been set for each column and applying them by hand to the appropriate table-cells. 剩下的任务是弄清楚已为每列设置了哪些格式设置属性,然后手动将其应用于适当的表单元格。 How best to do that, though? 但是,如何最好地做到这一点呢? One thought I had was to place all the <fo:table-column/> nodes into a variable, but then how would I use xpath to process these nodes? 我曾经想到的是将所有<fo:table-column />节点放入一个变量中,但是然后我将如何使用xpath处理这些节点? The other thought is there must be a way to do this using a temporary result tree, but have never used anything like this and am clueless about whether not this is possible, and if it is, how one would work with a temporary result tree. 另一个想法是,必须有一种使用临时结果树的方法,但是从未使用过这种方法,因此对于是否可行以及如何使用临时结果树一无所知。 I'm posting this question with labels XSLT 1.0 and XSLT 2.0 just to see if there is an answer, but I'm really constrained to using XSLT 1.0 for this problem. 我张贴这个问题有标签XSLT 1.0和XSLT 2.0只是为了看看没有一个答案,但我真的限制使用XSLT 1.0这个问题。

Edit: Someone requested a concrete example. 编辑:有人要求一个具体的例子。 A source document fragment might look something like this: 源文档片段可能看起来像这样:

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

ie a standard xhtml table, except with some attributes that would normally be represented using the style attribute. 即标准xhtml表,除了一些通常使用style属性表示的属性。

Then natural translation would be 那么自然翻译就是

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

However, there is a problem with this, namely none of the attributes in <table-column/> are automatically applied to the table cells in the corresponding column unless you specifically request that they be invoked using the from-table-colum() function (with the exception of width which is automatically applied). 但是,这存在一个问题,即<table-column />中的任何属性都不会自动应用于对应列中的表单元格,除非您特别要求使用from-table-colum()函数来调用它们(与宽度的除外,它自动应用)。 So, for example, for a table cell in the 3rd column of the table I would need to output the fo like this: 因此,例如,对于表格第三列中的表格单元格,我需要像这样输出fo:

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

and for a table cell in the 4th column I would need to output 对于第4列中的表格单元,我需要输出

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

The question is how do you know which attributes to look for for the table-cells in a particular column? 问题是您如何知道要为特定列中的表单元格查找哪些属性?

Well with XSLT 1.0 a variable containing result nodes is a result tree fragment, to convert it into a node set to be apply to apply XPath or process the nodes further you would use exsl:node-set or similar eg 在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"/>

The only difference in XSLT 2.0 is that you don't need the exsl:node-set function and its conversion operation, you can use any variable with temporary trees directly eg 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"/>

Caveat : I know nothing about XSL-FO; 警告 :我对XSL-FO一无所知; this is just something for you to use as a starting point. 这只是您可以使用的起点。

The way I understood your question, you want each table-cell to have the same list of attributes as the corresponding col in the source document. 以我理解您的问题的方式,您希望每个表单元格都具有与源文档中相应col相同的属性列表。 This would have been very easy to accomplish by looking at the position of the currently processed td and using that to look up the col at the same relative position. 通过查看当前处理的td的位置并使用该位置在相同的相对位置查找col ,将非常容易实现。 However, since some of the col elements have a span attribute, this is not as easy as that. 但是,由于某些col元素具有span属性,因此并非如此简单。

The solution I would suggest is to start by "enumerating" the col elements, so that there are exactly as many of them as there are columns. 我建议的解决方案是从“枚举” col元素开始,以便它们与列一样多。 With this in place, we can proceed as planned. 有了这个,我们可以按计划进行。

The following stylesheet: 以下样式表:

XSLT 1.0 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>

when applied to your input example, will produce the following result : 当应用于您的输入示例时,将产生以下结果

<?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>

This is assuming the table cells themselves do not have spans; 这是假设表单元格本身没有跨度。 otherwise this could get much more complex. 否则这可能变得更加复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM