使用xslt 2.0的嵌套级别的订单列表

时间:2017-10-27 13:33:56

标签: xml xslt

我有按顺序排列的许多列表的xml。但我需要将所有列表序列转换为嵌套级别。下面我提到了输入和预期输出。请任何人尝试。

输入

<body>
    <p>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
            <li id="(2)"> B </li>
        </list>
        <list level="2">
            <li id="(a)">is</li>
            <li id="(b)">was</li>
            <li id="(c)">other market</li>
        </list>
        <list level="3">
            <li id="(1)">first</li>
            <li id="(2)">second</li>
            <li id="(3)">third</li>
        </list>
    </p>
    <sec>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
        </list>
        <list level="2">
            <li id="(a)">is</li>
            <li id="(b)">was</li>
            <li id="(c)">other market</li>
        </list>
    </sec>
</body>

预期输出

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <p>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
            <li id="(2)"> B <list level="2">
                    <li id="(a)">is</li>
                    <li id="(b)">was</li>
                    <li id="(c)">other market <list level="3">
                            <li id="(1)">first</li>
                            <li id="(2)">second</li>
                            <li id="(3)">third</li>
                        </list>
                    </li>
                </list>
            </li>
        </list>
    </p>
    <sec>
        <list level="1" type="normal">
            <li id="(1)"> A <list level="2">
                    <li id="(a)">is</li>
                    <li id="(b)">was</li>
                    <li id="(c)">other market</li>
                </list>
            </li>
        </list>
    </sec>
</body>

任何人都请帮助我

我已经详细添加了一个输入。主要逻辑是根据级别属性的值对列表进行分组。

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <p>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
            <li id="(2)"> B </li>
        </list>
        <list level="2">
            <li id="(a)">is</li>
            <li id="(b)">was</li>
        </list>
        <list level="3">
            <li id="(1)">first</li>
            <li id="(2)">second</li>
        </list>
        <list level="2">
            <li id="(c)">ff</li>
            <li id="(d)">sss</li>
        </list>
        <list level="1">
            <li id="(3)">C</li>
            <li id="(4)">D</li>
        </list>
    </p>
    <sec>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
        </list>
        <list level="2">
            <li id="(a)">is</li>
            <li id="(b)">was</li>
            <li id="(c)">other market</li>
        </list>
    </sec>
</body>

预期的输出是。

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <p>
        <list level="1" type="normal">
            <li id="(1)"> A </li>
            <li id="(2)"> B <list level="2">
                    <li id="(a)">is</li>
                    <li id="(b)">was<list level="3">
                            <li id="(1)">first</li>
                            <li id="(2)">second</li></list></li>
                    <li id="(c)">ff</li>
                    <li id="(d)">sss</li>
                </list></li>
            <li id="(3)">C</li>
            <li id="(4)">D</li>
        </list>
    </p>
    <sec>
        <list level="1" type="normal">
            <li id="(1)"> A <list level="2">
                    <li id="(a)">is</li>
                    <li id="(b)">was</li>
                    <li id="(c)">other market</li>
                </list></li>
        </list>
    </sec>
</body>

1 个答案:

答案 0 :(得分:1)

首先从身份模板开始......

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

这至少会带你到中途!

您需要进行的转换之一是psec元素应该只有一个孩子; level1的list元素,因此可以使用另一个模板

来实现
<xsl:template match="*[list]">
    <xsl:copy>
        <xsl:apply-templates select="list[@level='1']"/>
    </xsl:copy>
</xsl:template>

然后,您只需要一个模板来匹配li中的最后一个list,然后复制它,并在孩提时修改以下list

<xsl:template match="li[not(following-sibling::*)]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <xsl:apply-templates select="../following-sibling::list[1]" />
    </xsl:copy>
</xsl:template>

完全放下这个......

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="*[list]">
        <xsl:copy>
            <xsl:apply-templates select="list[@level='1']"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="li[not(following-sibling::*)]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:apply-templates select="../following-sibling::list[1]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这确实假设您没有多个列表,每个项目下都有相同的levelid

编辑:如果您有多个具有相同levelid的列表项,则会变得有点复杂,但请尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="list" match="list" use="concat(generate-id(..), generate-id(preceding-sibling::list[@level = current()/@level - 1][1]))" />

    <xsl:template match="*[list]">
        <xsl:copy>
            <xsl:apply-templates select="list[@level='1'][1]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="li[not(following-sibling::*)]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:apply-templates select="key('list', concat(generate-id(../..), generate-id(..)))[1]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="list">
        <xsl:copy>
             <xsl:apply-templates select="@*" />
             <xsl:apply-templates select="key('list', concat(generate-id(..), generate-id(preceding-sibling::list[@level = current()/@level - 1][1])))/li" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>