将具有相同名称和相同属性的兄弟姐妹分组会导致撒克逊人出现异常

时间:2010-09-29 16:12:29

标签: xslt-2.0

我有一些必须转换为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

1 个答案:

答案 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>