在整个xml文档中选择空的元素之间的所有节点,将每个选区用div div打包
问题描述:
我正在研究将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。
答
我怎么能抓住每对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的答案,我将简化这个代码用他的方法。
+0
如果您的问题得到解答,请通过接受答案关闭它。 –
ypu意味着什么_“cb”标签并不总是兄弟姐妹._?他们并不总是_direct_兄弟姐妹? –