Группировка узлов по значению внуков - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть XML, у которого тип группы является самым глубоким узлом.Я должен сгруппировать подраздел XML, но в противном случае вернуть точно такой же XML.

Я смотрел на разные вопросы в Stackoverflow.В частности, я основываю свой ответ на этом: Группировка узлов XML по значению дочернего элемента в Xsl

Входной XML выглядит следующим образом:

<list>
    <element>
        <foo>
            <bar>
            </bar>
        </foo>
        <values>
            <position>
                <foo2>
                </foo2>
                <type>first
                </type>
            </position>
            <position>
                <foo2>
                </foo2>
                <type>second
                </type>
            </position>
            <position>
                <foo2>
                </foo2>
                <type>first
                </type>
            </position>
        </values>
    </element>    
</list>

Выходной XML должен выглядеть следующим образом:

<list>
    <element>
        <foo>
            <bar>
            </bar>
        </foo>
        <types>
            <first>
                <values>
                    <position>
                        <foo2>
                        </foo2>
                    </position>
                    <position>
                        <foo2>
                        </foo2>
                    </position>
                </values>
            </first>
            <second>
                <values>
                    <position>
                        <foo2>
                        </foo2>
                    </position>
                </values>
            </second>
        </types>
    </element>    
</list>

До сих пор у меня есть следующий XLST, который копирует преобразование сверху:

    <xsl:key name="types" match="type" use="."/>

    <xsl:template match="/list">
        <root>
            <xsl:apply-templates select="element/values/position/type[generate-id() = generate-id(key('types', .)[1])]"/>
            <xsl:apply-templates select="*|@*|comment()|text()"/>
        </root>
    </xsl:template>

    <xsl:template match="type">
        <xsl:variable name="currentType" select="."/>
        <xsl:element name="{$currentType}">
            <xsl:apply-templates select="*|@*|comment()|text()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="*">
        <xsl:element name="{local-name(.)}">
            <xsl:apply-templates select="*|@*|comment()|text()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Как только я добавлю шаблоны примененияна родительских узлах (в шаблоне, который соответствует типу) он больше ничего не возвращает:

    <xsl:template match="type">
        <xsl:variable name="currentType" select="."/>
        <xsl:element name="{$currentType}">
            <xsl:apply-templates select="../../*|@*|comment()|text()"/>
        </xsl:element>

1 Ответ

0 голосов
/ 13 февраля 2019

Во-первых: вы хотите сгруппировать position узлы по общим type - поэтому вы должны сделать так, чтобы ваш ключ соответствовал position и использовать type.

Как только вы это сделаете, это может бытьпросто:

XSLT 1.0

<xsl:stylesheet version="1.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:key name="pos-by-type" match="position" use="type"/>

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

<xsl:template match="values">
    <types>
        <xsl:for-each select="position[generate-id() = generate-id(key('pos-by-type', type)[1])]">
            <xsl:element name="{normalize-space(type)}">
                <values>
                    <xsl:apply-templates select="key('pos-by-type', type)"/>
                </values>
            </xsl:element>
        </xsl:for-each>
    </types>
</xsl:template>

<xsl:template match="type"/>

</xsl:stylesheet>

Обратите внимание, что это зависит от type, содержащего строку, которая является допустимым именем элемента XML.В вашем примере это не так, и я использовал normalize-space(), чтобы сделать это так.Но ваш реальный ввод может содержать другую строку с другими проблемами.

...