2016-06-14 36 views
1

我正在研究将XML(tei)文档转换为HTML的XSLT。 目标是创建可以样式显示为固定列的div。在整个xml文档中选择空的<cb>元素之间的所有节点,将每个选区用div 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。

+1

ypu意味着什么_“cb”标签并不总是兄弟姐妹._?他们并不总是_direct_兄弟姐妹? –

回答

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元素的兄弟姐妹。

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

+0

如果您的问题得到解答,请通过接受答案关闭它。 –

相关问题