Создайте новое дерево и назначьте переменную - PullRequest
0 голосов
/ 03 декабря 2010

У меня есть оригинальный XML-файл, подобный этому:

<list>
<no value="8">
    <no value="11">
        <no value="6">
            <no value="32"/>
            <no value="56"/>
        </no>
        <no value="9">
            <no value="111"/>
            <no value="67"/>
        </no>
    </no>
    <no value="7">
        <no value="5"/>
        <no value="11"/>
    </no>
</no>

А теперь я хочу поменять значение атрибута родительского узла и его дочерних узлов, например:

<list>
<no value="8">
    <no value="11">
        <no value="6">
            <no value="32"/>
            <no value="56"/>
        </no>
        <no value="9">
            <no value="111"/>
            <no value="67"/>
        </no>
    </no>
    <no value="11">
        <no value="5"/>
        <no value="7"/>
    </no>
</no>

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

<list>
<no value="111">
        <no value="...">
    ......
</no>

Может кто-нибудь дать мне предложение, пожалуйста?заранее спасибо

1 Ответ

0 голосов
/ 03 декабря 2010

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

Кроме того, это таблица стилей того, что я считаю желаемым преобразованием:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:param name="pReplace"/>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pReplace" select="$pReplace"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="no[@value][descendant::no/@value]">
        <xsl:param name="pReplace" select="''"/>
        <xsl:variable name="vSwaped"
                      select="descendant-or-self::no
                                 [contains($pReplace,
                                           concat(generate-id(),
                                                  '+'))]"/>
        <xsl:variable name="vPosition" select="count($vSwaped)+1"/>
        <xsl:variable name="vReplace">
            <xsl:for-each
                select="(ancestor::no[$vSwaped]|
                         descendant-or-self::no)[@value]">
                <xsl:sort select="@value"
                          data-type="number" order="descending"/>
                <xsl:if test="position()=$vPosition">
                    <xsl:value-of select="concat(generate-id(),'+',@value)"/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="value">
                <xsl:value-of select="substring-after($vReplace,'+')"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()">
                <xsl:with-param name="pReplace"
                                select="concat($pReplace,
                                               substring-before($vReplace,'+'),
                                               '+',generate-id(),'|')"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="no[@value][not(descendant::no/@value)]" name="find">
        <xsl:param name="pReplace" select="''"/>
        <xsl:param name="pFind" select="generate-id()"/>
        <xsl:variable name="vFound"
                      select="substring-before(
                                 substring-after(
                                    $pReplace,
                                    concat($pFind,'+')),
                                 '|')"/>
        <xsl:choose>
            <xsl:when test="$vFound!='' and $pFind != $vFound">
                <xsl:call-template name="find">
                    <xsl:with-param name="pReplace" select="$pReplace"/>
                    <xsl:with-param name="pFind" select="$vFound"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <xsl:attribute name="value">
                        <xsl:value-of select="//no[generate-id()=$pFind]
                                                  /@value"/>
                    </xsl:attribute>
                    <xsl:apply-templates select="node()"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<list>
    <no value="111">
        <no value="67">
            <no value="56">
                <no value="32"></no>
                <no value="6"></no>
            </no>
            <no value="11">
                <no value="8"></no>
                <no value="9"></no>
            </no>
        </no>
        <no value="11">
            <no value="5"></no>
            <no value="7"></no>
        </no>
    </no>
</list>

Объяснение : Родитель берет N-ую максиму своей ветви.N определяется как количество уже взятых максимумов из его ветви плюс один.Если из его ветви уже взят максимум, предки также принимаются в расчет максимума.Последние листья следуют по пути замен, чтобы найти их значение.

Это больше похоже на статическое отображение между входным состоянием и состоянием вывода, за исключением последних листьев.

Также обратите внимание, что I 'Мы используем очень общий шаблон, поэтому заботятся только о no элементах с value атрибутами.И могут быть любые другие элементы, которые они просто скопировали бы.

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