for-each-group中的分组不正确

时间:2011-03-22 23:45:56

标签: xslt xslt-2.0

我有以下XML,我正在尝试生成HTML文件。

<?xml version="1.0" encoding="UTF-8"?>
<text>
    <body>
        <milestone unit="fragment"/>
            <div>

                <p>First line text in FIRST fragment</p>
                <p>Second line <seg>text in FIRST</seg> fragment</p>
                <p>Third line text in FIRST fragment</p>

                <milestone unit="fragment"/>
                <p>First line text in SECOND fragment</p>
                <p>Second line <seg>text in SECOND </seg> fragment</p>
                <p>Third line text in SECOND fragment</p>

                <milestone unit="fragment"/>
                <p>First line text in THIRD fragment</p>
                <p>Second line <seg>text in THIRD </seg> fragment</p>
                <p>Third line text in THIRD fragment</p>

            </div>
    </body>
</text>

预期的HTML输出:

HTML 1:
<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<p>Third line text in FIRST fragment</p>


HTML 2:
<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND </span> fragment</p>
<p>Third line text in SECOND fragment</p>

HTML 3:
<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD </span> fragment</p>
<p>Third line text in THIRD fragment</p>

这是我用于每个组的XSLT,用于在“里程碑”标记之间对节点进行分组,但是分组不会按预期发生。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="html" name="html" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" include-content-type="no"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="body">
        <xsl:for-each-group select="descendant::*" group-starting-with="milestone[@unit='fragment']">

            <xsl:variable name="currFragNumber">
                    <xsl:number count="milestone[@unit='fragment']" level="any" from="text"/>
                </xsl:variable>
                                <xsl:result-document href="{$currFragNumber}.html" format="html">
                    <xsl:apply-templates select="current-group()" />
                </xsl:result-document>

        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="p">
        <p>
            <xsl:apply-templates/>
        </p>
    </xsl:template>

    <xsl:template match="seg">
        <span>
            <xsl:apply-templates/>
        </span>
    </xsl:template>
</xsl:stylesheet>

以下是转换后的输出。

HTML 1:
<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<p>Third line text in FIRST fragment</p>

<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND</span>fragment</p>
<p>Third line text in SECOND fragment</p>

<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD</span>fragment</p>
<p>Third line text in THIRD fragment</p>

<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<span>text in FIRST</span>
<p>Third line text in FIRST fragment</p>


HTML 2:
<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND </span> fragment</p>
<span>text in SECOND </span>
<p>Third line text in SECOND fragment</p>

HTML 3:
<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD </span> fragment</p>
<span>text in THIRD </span>
<p>Third line text in THIRD fragment</p>

我试图理解为什么第一个当前组()(即第一个“里程碑”)与整个文档匹配,而不仅仅是“里程碑”标记之间的节点。

2 个答案:

答案 0 :(得分:1)

问题是你正在选择div,正如我在评论中所建议的那样。

使用:

<xsl:for-each-group select="div/*" 
                    group-starting-with="milestone[@unit='fragment']">

它将正确序列化三个结果文档。请注意,您可能会忘记第一个milestone,因为根据http://www.w3.org/TR/xslt20/#xsl-for-each-group

  

如果是group-starting-with属性   存在,那么它的价值必须是a   图案。在这种情况下,项目在   人口必须都是节点。

     

人口中的节点是   检查人口秩序。如果一个   节点匹配模式,或是   人口中的第一个节点 * ,然后是a   创建新组和节点   成为它的第一个成员。除此以外,   节点分配给同一组   作为其前面的节点   人口。

*:重点是我的。

答案 1 :(得分:0)

修改:在我最初的回复(下方)中,我认为select属性的值必须是一个模式,现在我发现我被规范误导了。

在这种情况下,报告的行为很可能是一个错误。

@Jahangir,祝贺发现了至少三个XSLT 2.0处理器的错误。


W3C XSLT 2.0规范(关于select的{​​{1}}属性):

  

“•如果是group-starting-with属性   存在,那么它的价值必须是a   模式“。

模式规则只允许在模式中使用xsl:for-each-groupchild::轴。

因此,attribute::不允许作为模式。我想XSLT处理器将其视为“可恢复的错误”并将其自身的操作视为恢复。

解决方案是将第一个descendant::*元素放在milestone的紧随其后的兄弟的适当位置,并更改div xsl:for-each-group {{1 }} DIV / *`:

select attribute of

to: