XSLT разделяет повторяющиеся элементы на отдельные группы, сохраняя при этом братьев и сестер - PullRequest
2 голосов
/ 06 мая 2011

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

<group>
    <b074>11</b074>
    <b075>03</b075>
    <b076>9</b076>
    <b075>04</b075>
    <b076>12</b076>
</group>
<group>
    <b074>11</b074>
    <b075>04</b075>
    <b076>4</b076>
</group>

был преобразован в:

<group>
    <b074>11</b074>
    <b075>03</b075>
    <b076>9</b076>
</group>
<group>
    <b074>11</b074>
    <b075>04</b075>
    <b076>12</b076>
</group>
<group>
    <b074>11</b074>
    <b075>04</b075>
    <b076>4</b076>
</group>

EDIT: первая группа в исходных данных имеет повторяющиеся элементы.Например, элемент <b075> встречается дважды.Я хотел бы, чтобы второе вхождение <b075> было в новой группе в результате.Это то, что я имел в виду под уникальным набором.

РЕДАКТИРОВАТЬ # 2: Забыл упомянуть, что, когда второй <b075> выдвинут в свою собственную группу, его брат <b074> "копируется" вместе.Это то, что я имел в виду, оставляя братьев и сестер.

РЕДАКТИРОВАТЬ # 3: (Я извиняюсь, я должен был объяснить это более подробно в первый раз) То, как вы знаете, что <b074> относится к полученной группе, потому что этопроисходит один раз.Все элементы в исходной группе, которые встречаются один раз, совместно используются всеми полученными группами.Повторяющиеся элементы также будут перечислены последовательно, что означает, что если элементы <b075> и <b076> повторяются, они будут рядом друг с другом, <b075>, затем сразу <b076>.Таким образом, число результирующих групп - это количество таких повторяющихся фрагментов элементов (2 в случае этого примера).

К сожалению, я новичок в XSLT, но я безуспешно пытался применить вариантырешения, найденные в XSLT разделяет дерево в дочернем узле и Перемещают элементы-разделители вверх в иерархии xml , так как они кажутся очень близкими к тому, что я пытаюсь выполнить.

Я использую 1.0 - 2.0 не вариант для меня.Любая помощь будет оценена.

1 Ответ

4 голосов
/ 06 мая 2011

Если я правильно понимаю ваши условия, вам нужно следующее преобразование:

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

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="group">
        <xsl:apply-templates select="*[1]" mode="group"/>
    </xsl:template>

    <xsl:template match="*" mode="group">
        <xsl:param name="level" select="0"/>
        <xsl:variable name="name" select="name()"/>
        <xsl:variable name="needs-group" select="count( preceding-sibling::*[ name() = $name ] ) = $level"/>
        <xsl:if test="$needs-group">
            <group>
                <xsl:apply-templates select="preceding-sibling::*[ name() != $name ]" mode="item-group">
                    <xsl:with-param name="level" select="$level"/>
                </xsl:apply-templates>

                <xsl:apply-templates select="."/>

                <xsl:apply-templates select="following-sibling::*[ name() != $name ]" mode="item-group">
                    <xsl:with-param name="level" select="$level"/>
                </xsl:apply-templates>
            </group>
        </xsl:if>

        <xsl:apply-templates select="following-sibling::*[1]" mode="group">
            <xsl:with-param name="level" select="$level + $needs-group"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="*" mode="item-group">
        <xsl:param name="level"/>
        <xsl:variable name="name" select="name()"/>
        <xsl:if test="( count( preceding-sibling::*[ name() = $name ] ) = $level ) or ( count( ../*[ name() = $name ] ) &lt;= $level and not( following-sibling::*[ name() = $name ] ) )">
            <xsl:apply-templates select="."/>
        </xsl:if>
    </xsl:template>

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

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...