非常感谢您提供有关分组实际工作方式的帮助

时间:2018-11-28 18:01:03

标签: xslt-2.0

我正在努力弄清不同分组技术的工作原理。是什么原因导致一个组,如何定义每个组以及如何为每个组形成密钥。

如果我想使用“ group-adjacent”将特定元素名称的所有后续同级移动到给定类型的先前同级中的第一个。这可行吗?我知道如何使用递归模板以及在某种程度上使用xslt 1.0中的键来做到这一点。但是我无法让2.0组为我工作。

让我们说,由于在这个简单的xml中,无花果和前一个para元素之间没有其他种类的元素,因此我想将所有无花果元素都移到第一个前一个para中。

<root>
    <first_lvl>
        <title>First heading</title>
        <para>First para under first heading</para>
        <para>Second para under first heading</para>
        <fig>fig1</fig>
        <fig>fig 2</fig>
        <table>Table A</table>
        <fig>fig 3</fig>
        <para>Third para under first heading</para>
        <para>Fourth para under first heading</para>
        <fig>fig4</fig>
    </first_lvl>
</root>

所需结果:

<root>
    <first_lvl>
        <title>First heading</title>
        <para>First para under first heading</para>
        <para>Second para under first heading
            <fig>fig1</fig>
            <fig>fig 2</fig>
        </para>
        <table>Table A</table>
        <fig>fig 3</fig>
        <para>Third para under first heading</para>
        <para>Fourth para under first heading
            <fig>fig4</fig>
        </para>
    </first_lvl>
</root>

我该如何设置一个分组来处理每个紧接的无花果元素?

这不起作用:

<xsl:template match=para[following-sibling::*[1][self::fig]]>
    <xsl:for-each-group select"folowing-sibling::*" group-adjacent="boolean(self::fig)">
        <xsl:apply-templates select="current-group()" mode="move"/>
    </xsl:for-each-group>
</xsl:template>

然后我添加了一个模板,用于为para中的每个无花果构建内容,并且在以后的处理中出现时忽略这些无花果。

虽然没有运气。

除了它们是无花果元素之外,我没有其他值可以分组。

我在这里想念什么?

1 个答案:

答案 0 :(得分:0)

我会先从group-starting-with的{​​{1}}开始,然后是para,然后在内部使用fig仅识别相邻group-adjacent的第一组s。 XSLT的冗长性看起来有点令人费解,但据我所知,您的要求可以完成工作:

fig

https://xsltfiddle.liberty-development.net/6qVRKxh

我已自由使用XSLT 3而不是2,但是您只需要阐明<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0"> <xsl:mode on-no-match="shallow-copy"/> <xsl:output method="xml" indent="yes" /> <xsl:template match="*[para and fig]"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:for-each-group select="*" group-starting-with="para[following-sibling::*[1][self::fig]]"> <xsl:choose> <xsl:when test="self::para[following-sibling::*[1][self::fig]]"> <xsl:variable name="para-head" select="."/> <xsl:for-each-group select="tail(current-group())" group-adjacent="boolean(self::fig)"> <xsl:choose> <xsl:when test="position() = 1"> <xsl:copy select="$para-head"> <xsl:apply-templates select="node(), current-group()"/> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet> 声明的身份转换并确保您使用

xsl:mode on-no-match="shallow-copy"

仅使用<xsl:element name="{name($para-head)}" namespace="{namespace-uri($para-head)}"> <xsl:apply-templates select="$para-head/node(), current-group()"/> </xsl:element> 而不是XSLT 3 xsl:copy

select

,例如,使用 <xsl:copy select="$para-head"> <xsl:apply-templates select="node(), current-group()"/> </xsl:copy> 代替XPath 3 tail函数

subsequence

http://xsltransform.hikmatu.com/bFDb2BN

另一方面,我不确定是否尝试不使用<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:output method="xml" indent="yes" /> <xsl:template match="*[para and fig]"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:for-each-group select="*" group-starting-with="para[following-sibling::*[1][self::fig]]"> <xsl:choose> <xsl:when test="self::para[following-sibling::*[1][self::fig]]"> <xsl:variable name="para-head" select="."/> <xsl:for-each-group select="subsequence(current-group(), 2)" group-adjacent="boolean(self::fig)"> <xsl:choose> <xsl:when test="position() = 1"> <xsl:element name="{name($para-head)}" namespace="{namespace-uri($para-head)}"> <xsl:apply-templates select="$para-head/node(), current-group()"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:transform> 而是匹配xsl:for-each-group的模板,然后消耗同级para[following-sibling::*[1][self::fig]]之后的模板(可以很容易地在带有fig的XSLT 3并不更紧凑:

xsl:iterate

https://xsltfiddle.liberty-development.net/6qVRKxh/3