How can i get a sequence of elements with a define

2019-06-11 03:48发布

问题:

How ca i use an xslt template to get from this:

<attribute name="Foo" level="1"/>
<attribute name="Bar" level="2"/>
<attribute name="Lorem" level="2"/>
<attribute name="Ipsum" level="3"/>

to a structure like this:

<attribute name="Foo">
    <attribute name="Bar"/>
    <attribute name="Lorem">
        <attribute name="Ipsum"/>
    </attribute>
</attribute>

I can use XSLT and XPATH 2.0 and i tried different things with grouping but i don't know how to get a recursion into it.

回答1:

If you use a function applying a for-each-group group-starting-with you get

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf">

    <xsl:output indent="yes"/>

    <xsl:function name="mf:group" as="element(attribute)*">
        <xsl:param name="attributes" as="element(attribute)*"/>
        <xsl:param name="level" as="xs:integer"/>
        <xsl:for-each-group select="$attributes" group-starting-with="attribute[@level = $level]">
            <attribute name="{@name}">
                <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
            </attribute>
        </xsl:for-each-group>
    </xsl:function>

    <xsl:template match="root">
        <xsl:sequence select="mf:group(attribute, 1)"/>
    </xsl:template>

</xsl:transform>

which transforms

<root>
    <attribute name="Foo" level="1"/>
    <attribute name="Bar" level="2"/>
    <attribute name="whatever" level="3"/>
    <attribute name="Lorem" level="2"/>
    <attribute name="Ipsum" level="3"/>
    <attribute name="foobar" level="3"/>
</root>

into

<attribute name="Foo">
   <attribute name="Bar">
      <attribute name="whatever"/>
   </attribute>
   <attribute name="Lorem">
      <attribute name="Ipsum"/>
      <attribute name="foobar"/>
   </attribute>
</attribute>


标签: xml xslt xpath