使用XSLT 2.0将XML分解为多个部分

时间:2016-02-11 23:14:37

标签: xslt xslt-2.0

我被赋予XML作为输入,我无法控制结构。我需要将XML分解为多个部分并分别处理每个部分。下面是我要处理的文件的一个非常简化的版本。

我正在尝试使用XSLT 2.0的分组功能通过使用<breakEle>标记作为部分边界来分解此XML。 <breakEle>也可以出现在任何级别。我正在尝试使用XSLT 2.0做什么?我使用Muenchian分组成功地使用XSLT 1.0完成了这项工作,但是如果可以的话,我想摆脱它。

示例输入:

<item class="poem">
    <div>
        <div>
            <p>paragraph 1</p>
            <breakEle groupNum="1"/>
        </div>
        <div>
            <p>Paragraph in another div.</p>
        </div>
        <breakEle groupNum="2"/>
        <div>
            <div>
                <h4>header</h4>
                <p>1st line</p>
                <p>2nd line</p>
                <br/>
                <p>3rd line</p>
                <p>4th line</p>
                <page n="100"/>
                <p>5th line</p>
            </div>
            <breakEle groupNum="3"/>
        </div>
    </div>
</item>

我尝试使用的内容:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    exclude-result-prefixes="xs xd"
    version="2.0">
    <xsl:template match="/">
        <newRoot>
            <xsl:copy>
                <xsl:for-each-group select="*" group-ending-with="breakEle">
                    <div num="{@groupNum}">
                        <xsl:copy-of select="current-group()"/>
                    </div>
                </xsl:for-each-group>
            </xsl:copy>
        </newRoot>
    </xsl:template>
</xsl:stylesheet>

想结束这样的事情:

<newRoot>
    <div num="1">
        <p>paragraph 1</p>
    </div>
    <div num="2">
        <p>Paragraph in another div.</p>
    </div>
    <div num="3">
        <h4>header</h4>
        <p>1st line</p>
        <p>2nd line</p>
        <br/>
        <p>3rd line</p>
        <p>4th line</p>
        <page n="100"/>
        <p>5th line</p>
    </div>
</newRoot>

1 个答案:

答案 0 :(得分:0)

以下样式表在应用于给定示例时返回预期结果。

它假设每个组只应包含叶元素。

XSLT 2.0

<xsl:stylesheet version="2.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:template match="/item">
    <newRoot>
        <xsl:for-each-group select=".//*[not(*)]" group-ending-with="breakEle">
            <div num="{current-group()[last()]/@groupNum}">
                <xsl:copy-of select="current-group()[not(self::breakEle)]"/>
            </div>
        </xsl:for-each-group>
    </newRoot>
</xsl:template>

</xsl:stylesheet>