группировать братьев и сестер, последовательно определяя первый узел определенного типа

Не уверен, что это описание лучшее ... но с учетом этого xml:

<?xml version="1.0"?>
<root>
    <type1 num="1" first="1"/>
    <type1 num="2" />
    <type2 num="3" />
    <type2 num="4" />
    <type1 num="5" first="2"/>
    <type1 num="6" />
    <type2 num="7" />
    <type2 num="8" />
    <type1 num="9" first="3"/>
    <type1 num="10" />
    <type2 num="11" />
    <type2 num="12" />

</root>

Я хочу углубить иерархию и добавлять новый узел «группа» каждый раз, когда я нажимаю первый в последовательности узлов типа 1. (примечание: @first присутствует только для того, чтобы я мог видеть, какой именно узел собирал шаблон ... Я не хочу использовать его для запуска группы)

Вот моя таблица стилей.

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="kFirstText" match="*" use="generate-id(preceding-sibling::type1[not(preceding-sibling::*[1][self::type1])][1])"/>

<xsl:template match="/">
    <newroot>
        <xsl:apply-templates/>
    </newroot>
</xsl:template>

<xsl:template match="type1[not(preceding-sibling::*[1][self::type1])]">
    <group>
        <type1>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="first-in-group">true</xsl:attribute>
        </type1>
        <xsl:copy-of select="key('kFirstText', generate-id())"/>
    </group>
</xsl:template>
</xsl:stylesheet>

И результат, который я получаю:

<?xml version='1.0' ?>
<newroot>
    <group><type1 num="1" first="1" first-in-group="true"/><type1 num="2"/><type2 num="3"/><type2 num="4"/><type1 num="5" first="2"/></group>
    <group><type1 num="5" first="2" first-in-group="true"/><type1 num="6"/><type2 num="7"/><type2 num="8"/><type1 num="9" first="3"/></group>
    <group><type1 num="9" first="3" first-in-group="true"/><type1 num="10"/><type2 num="11"/><type2 num="12"/></group>
</newroot>

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

Я также понял, что немного не понимаю, что именно берет ключ. Я считаю, что он собирает любой узел, который следует непосредственно за предыдущим экземпляром type1, у которого нет type1 сразу за ним ... это верно?

Я также попытался исключить этот узел (@ num = "5") в @match, используя тот же xpath в шаблоне, но это было просто проигнорировано. Есть идеи, как выполнить то, что я описал выше?

Благодарность!


person badperson    schedule 22.06.2015    source источник


Ответы (1)


Попробуйте так:

<xsl:key name="kFirstText" match="*[not(self::type1[not(preceding-sibling::*[1][self::type1])])]" use="generate-id(preceding-sibling::type1[not(preceding-sibling::*[1][self::type1])][1])"/>

Это исключает «ведущие» узлы из группы, полученной с помощью ключа.

person michael.hor257k    schedule 22.06.2015
comment
спасибо, я пробовал использовать match = type2 | type1 [not (previous-sibling :: * [1] [self :: type1])], но это было проигнорировано ... ваш сработал отлично - person badperson; 23.06.2015