Измените структуру xml, сгруппировав элементы xml на основе атрибута.

Мне нужно перегруппировать элементы xml в одной и той же структуре xml на основе атрибутов. У меня есть xml, подобный этому.

<a>
    <b>
        <c>
            <d1 att2="t1">test 1</d1>
            <d1>test 2</d1>
            <d1>test 3</d1>
            <d1 att2="t1">test 4</d1>
        </c>
    </b>
</a>

Мне нужно преобразовать этот xml в,

<a>
    <b>
        <c>
            <d1 att2="t1">test 1</d1>
            <d1 att2="t1">test 4</d1>
        </c>
    </b>
</a>
<a>
    <b>
        <c>
            <d1>test 2</d1>
        </c>
    </b>
</a>
<a>
    <b>
        <c>
            <d1>test 3</d1>
        </c>
    </b>
</a>

person chavsh    schedule 04.12.2014    source источник
comment
Для подтверждения, если att2 совпадает, то сгруппировать их, а если отличается или отсутствует, то новую группу? У вас есть доступ к процессору xslt 2? Пожалуйста, пометьте как таковой?   -  person StuartLC    schedule 04.12.2014
comment
@StuartLC ваше предположение верно, и у меня есть доступ к процессору xslt 2.   -  person chavsh    schedule 04.12.2014


Ответы (1)


Это действительно скучное / ручное усилие, но, похоже, оно выполняет свою работу. Шаблон применяет отдельные ветки к элементам с атрибутами @att2 и без них.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <root>
            <xsl:for-each-group select="//d1[@att2]" group-by="@att2">
                <a>
                    <b>
                        <c>
                            <xsl:for-each select="current-group()">
                                <xsl:apply-templates select="." mode="nowrapper"></xsl:apply-templates>
                            </xsl:for-each>
                        </c>
                    </b>
                </a>
            </xsl:for-each-group>
            <xsl:apply-templates select="//d1[not(@att2)]" mode="wrapper" />
        </root>
    </xsl:template>

    <xsl:template match="d1" mode="wrapper">
        <a>
            <b>
                <c>
                    <xsl:apply-templates select="." mode="nowrapper" />
                </c>
            </b>
        </a>
    </xsl:template>

    <xsl:template match="d1" mode="nowrapper">
        <xsl:copy-of select="." />
    </xsl:template>

</xsl:stylesheet>
person StuartLC    schedule 04.12.2014
comment
Спасибо @StuartLC за вашу помощь. - person chavsh; 04.12.2014