1

我正在使用 XSLT 将 XML (tei) 文档转换为 HTML。目标是创建可以设置样式以显示为固定列的 div。

在文档中,列开始由 2 个空元素(里程碑和 cb)表示。“里程碑”表示文本流中的列数现在等于 n 属性。“cb” 标记一列的开始,它的 n 属性表示它在从左到右的顺序中的顺序。“cb”标签并不总是兄弟姐妹。

示例 xml:

<p>
  <milestone unit="column" n="2"/>
  <cb n="1"/>
  M. Dudley
  <lb/>
  H. E. Ernshimer
  <lb/>
  M. M. Cash
  <lb/>
  John Wheatly
  <lb/>
  Jno W. Cash
  <lb/>
  <cb n="2"/>
  R. L. Wilson
  <lb/>
  R. B. Ratliff L.C.C.
  <lb/>
  G. D Watkins Clk
  <lb/>
  A. C. Mayes
  <lb/>
  <pb/>
</p>
<p>
   <note place="left margin">Jury 1863 Nov.</note>
   <lb/>
   <cb n="1"/>
   D C Mitchenssson
   <lb/>
   A. W. Forde, Tm P
   <lb/>
   L S Thomson
   <lb/>
   Louis Martin
   <hi rend="sup">c</hi>
   Casslin
   <lb/>
   E. M. Stevens
   <lb />
   <cb n="2"/>
   O Ross Baker Clk Caldwell County Court
   <lb/>
   N. Jones
   <lb/>
   S. W. M
   <milestone unit="column" n="1"/>
   <pb/>
   <lb/>
   John Garrett
</p>

期望的结果如下。类等于其前一个里程碑的 n 属性的 div:

<div class="column 2">
    M. Dudley<br />
    H. E. Ernshimer<br />
    M. M. Cash<br />
    John Wheatly<br />
    Jno W. Cash<br />
    ...
</div>
<div class="column 2">
    R. L. Wilson<br />
    R. B. Ratliff L.C.C.<br />
    G. D Watkins Clk<br />
    A. C. Mayes<br />
    Jas Crenshaw<br />
</div>

如何获取每对 cb 标签之间的所有内容,并将内容包装在包含的 div 中?我尝试过的一切都会导致一系列嵌套的 div。

4

2 回答 2

0

我想出了一个可行的解决方案。可能不优雅,但它适用于我的目的。我会在这里发帖,以防将来对其他人有用。

<!-- add a white space in empty milestone so it doesn't wrap around other elements -->
<xsl:template match="tei:milestone">
  <xsl:variable name="milenum" select="@n" />
  <milestone>
    <xsl:attribute name="n">
       <xsl:value-of select="$milenum" />
    </xsl:attribute>
    <xsl:text> </xsl:text>
  </milestone>
</xsl:template>

<!-- add a white space in empty cb so it doesn't wrap around other elements -->
<xsl:template match="tei:cb">
   <xsl:variable name="num" select="@n" />
   <cb>
      <xsl:attribute name="n">
         <xsl:value-of select="$num" />
      </xsl:attribute>
      <xsl:text> </xsl:text>
   </cb>
</xsl:template>

<!-- wrap content following cb elements in a div, with a class indicating the number of columns in the preceding milestone n attribute (if milestone n=2, then div class=column1of2 or div class=column2of2) -->
<xsl:template match="tei:p[tei:cb]">
    <!-- to print text before the first milestone -->
    <xsl:apply-templates select="node()[not(preceding::tei:milestone)]" />
    <xsl:for-each select="tei:cb">
      <xsl:variable name="count" select="position()" />
      <div>
         <xsl:variable name="numberofcolumns" select="preceding::tei:milestone[1]/@n" />
         <xsl:variable name="n" select="@n" />
         <xsl:attribute name="class">
           <xsl:text>column</xsl:text>
           <xsl:value-of select="$n" />
           <xsl:text>of</xsl:text>
           <xsl:value-of select="$numberofcolumns" />
         </xsl:attribute>
         <xsl:apply-templates select="following-sibling::node()[preceding-sibling::tei:cb[1][@n=$n] and count(preceding-sibling::tei:cb)=$count and preceding::tei:milestone[1][@n>1] and not(self::tei:milestone)]" />
       </div>
     </xsl:for-each>
 </xsl:template>

这输出:

<milestone n="2"> </milestone>
<div class="column1of2">
</div>
<div class="column2of2">
</div>
<div class="column1of2">
</div>
<div class="column2of2">
</div>

现在我从@michael.hor257k 看到了答案,我将用他的方法简化这段代码。

于 2016-06-21T23:16:02.177 回答
0

如何获取每对 cb 标签之间的所有内容

我没有看到您有一将列的内容括起来的标签 - 只有顶部cb的前导元素。cb

IIUC,你想做这样的事情:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="txt-by-col" match="text()" use="generate-id(preceding-sibling::cb[1])" />

<xsl:template match="/">
    <root>
        <xsl:for-each select="//cb">
            <div class="column {preceding::milestone[1]/@n}">
                <xsl:for-each select="key('txt-by-col', generate-id())">
                    <xsl:value-of select="." />
                    <br/>
                 </xsl:for-each>    
            </div>
        </xsl:for-each>
    </root>
</xsl:template>

</xsl:stylesheet>

这并不是假设列的所有文本节点都是前导cb元素的兄弟节点。

于 2016-06-14T06:45:41.340 回答