选择<cb>整个 xml 文档中空元素之间的所有节点,用 div 包装每个选择



我正在研究一个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。

如何抓取每对 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元素的同级。

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

<!-- 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 的答案,我将用他的方法简化这段代码。

相关内容

  • 没有找到相关文章

最新更新