我有一些必须转换为xsl-fo的xml文档(类似于docbook)。一些文件包含诗歌,诗歌的线条用不同的p标签写成。这些经文用br标签分隔。有“页面”标签是不相关的,应该被忽略。
典型代码示例:
<h4>Headline</h4>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
<h4>Other headline</h4>
对于xsl-fo输出,我想将一节经文的所有文本收集到一个单独的fo:block中。现在,该机制适用于上面的代码结构,但也有一些例外。实际的方法是决定每个p标签: - 我是一节经文的第一行吗? - 如果是:收集本节的所有文本并将其写入fo:block,使用实际(第一个)p标签的属性来设置块的格式 - 如果不是:内容被处理过,不做任何事。
第一行是一个p标签,紧接着是h4或br标签(或者一个页面标签本身紧跟一个br标签)。那个很容易开发。
收集一节经文的文本对于给定的例子很容易:将所有兄弟姐妹分组,用h4或br标签定义组,然后我取第一组并使用所有p标签(忽略页面标签之间或结束h4或br标签)。
在代码中:
<xsl:for-each-group select="following-sibling::*" group-ending-with="br|h4">
<xsl:if test="position()=1">
<xsl:for-each select="current-group()[not(self::h4) and not(self::br) and not(self::page)]">
<xsl:apply-templates/>&crt;
</xsl:for-each>
</xsl:if>
</xsl:for-each-group>
现在给一个类似的代码示例:
<h4>Headline</h4>
<p class="center">1</p>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p class="center">2</p>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
<h4>Other headline</h4>
现在,居中的p就像是以下经文的副标题。这不是一节经文,但就我的目的来说,如果它与真实经文的文本分开就足够了。因此,获得当前经文的所有文本的略微变化的规则是: 将所有兄弟姐妹分组,用h4或br标签定义组,或者用另一个类然后是当前p标签的ap标签,然后我取第一组并使用所有p标签(忽略之间)页面标签或结尾的h4或br标签)。
因此,我将当前p标记的class属性的值存储在名为attributes的变量中,并将组规则定义为:
<xsl:for-each-group select="following-sibling::*" group-ending-with="br|h4|p[normalize-space(@class) != $attributes]">
在eturn中,当试图确定p标签是否是一节经文的第一行时,它不仅可以在h4或br之前,还可以在另一个具有不同类属性值的p标签之前。
现在,这在我使用Saxon-B9.1.0.6的Oxygen测试环境中工作正常。但是转换必须使用Saxon9.jar在java中执行,并且在xsl:for-each-group的group-ending-with属性中使用变量会导致异常。
现在我有点陷入困境。
是否可以更好地定义分组条件?或者这可能不是通过分组完成,而是采用完全不同的方法?
源文件是原样的,标记可能不是最佳的,但它是原样的。转型并不新鲜,但后来又适应了我们的需求。之前简单地避免使用带有诗歌的源代码,但我想为此找到解决方案。
非常感谢任何帮助。
致以最诚挚的问候,
Christian Kirchhoff
答案 0 :(得分:1)
此样式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="div[@class='poem']">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="*" group-ending-with="br|h4">
<div class="strophe">
<xsl:copy-of select="current-group()/self::p[not(@class)]"/>
</div>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用此输入:
<div class="poem">
<h4>Headline</h4>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
</div>
输出:
<div class="poem">
<div class="strophe">
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
</div>
<div class="strophe">
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<p>3rd line of 2nd verse</p>
</div>
</div>
使用此输入:
<div class="poem">
<h4>Headline</h4>
<p class="center">1</p>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p class="center">2</p>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
</div>
输出:
<div class="poem">
<div class="strophe">
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
</div>
<div class="strophe">
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<p>3rd line of 2nd verse</p>
</div>
</div>
所以,这个样式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="div[@class='poems']">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="*[preceding-sibling::h4]"
group-starting-with="h4">
<div class="poem">
<xsl:for-each-group select="current-group()"
group-ending-with="br">
<div class="strophe">
<xsl:copy-of select="current-group()
/self::p[not(@class)]"/>
</div>
</xsl:for-each-group>
</div>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用此输入:
<div class="poems">
<h3>Poems</h3>
<h4>Headline</h4>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
<h4>Headline</h4>
<p class="center">1</p>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p class="center">2</p>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
</div>
输出:
<div class="poems">
<div class="poem">
<div class="strophe">
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
</div>
<div class="strophe">
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<p>3rd line of 2nd verse</p>
</div>
</div>
<div class="poem">
<div class="strophe">
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
</div>
<div class="strophe">
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<p>3rd line of 2nd verse</p>
</div>
</div>
</div>