Как отсортировать один XML-узел в зависимости от порядка другого?

Мне стыдно признаться, что я потратил 7 часов подряд, пытаясь сделать эту работу. Я хочу отсортировать вывод из первого узла, используя порядок второго узла.

XML

<?xml version="1.0" encoding="utf-8" ?>
<data>
    <content>
        <section link-id="86" link-handle="Start" value="Start" />
        <section link-id="23" link-handle="george-orwell" value="Orwell, George" />
        <section link-id="24" link-handle="aldous-huxley" value="Huxley, Aldous" />
        <section link-id="26" link-handle="robert-lewis-stevenson" value="Stevenson, Robert Louis" />
    </content>
    <datasource>
        <entry id="86">
            <name handle="start">Start</name>
            <order handle="0">0</order>
        </entry>
        <entry id="23">
            <name handle="george-orwell">Orwell, George</name>
            <order handle="1">1</order>
        </entry>
        <entry id="26">
            <name handle="robert-lewis-stevenson">Stevenson, Robert Louis</name>
            <order handle="2">2</order>
        </entry>
        <entry id="24">
            <name handle="aldous-huxley">Huxley, Aldous</name>
            <order handle="3">3</order>
        </entry>
    </datasource>
</data>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="sort-key" match="/data/datasource/entry" use="." />
    <xsl:template match="data">
        <html>
            <body>
                <xsl:apply-templates select="content" />
            </body>
        </html>
    </xsl:template>
    <xsl:template match="content">
        <xsl:apply-templates select="section">
            <xsl:sort select="key('sort-key', .)/@id"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="section">
        Section: <xsl:value-of select="@value"/>
    </xsl:template>
</xsl:stylesheet>

Текущий и неправильный вывод

<?xml version="1.0" encoding="utf-16"?>
<html><body>
Section: Start
Section: Orwell, George
Section: Huxley, Aldous
Section: Stevenson, Robert Louis</body>
</html>

person mmcglynn    schedule 25.11.2013    source источник
comment
Какое значение имеют критерии заказа?   -  person Kirill Polishchuk    schedule 25.11.2013
comment
Нет других критериев, кроме как быть упорядоченным, как второй узел. Причина этого направляющего узла в том, что не используются другие критерии (альфа и т. д.). Ищем способ явно установить.   -  person mmcglynn    schedule 25.11.2013


Ответы (1)


Судя по вашему XML, вы действительно хотите искать элементы entry по их id, поэтому вам, вероятно, следует определить свой ключ следующим образом:

<xsl:key name="sort-key" match="/data/datasource/entry" use="@id" />

Затем, предполагая, что атрибут handle всегда последовательно указан, команда xsl:sort будет выглядеть так:

<xsl:sort select="key('sort-key', @link-id)/order/@handle"/>

Попробуйте этот XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="sort-key" match="/data/datasource/entry" use="@id" />
    <xsl:template match="data">
        <html>
            <body>
                <xsl:apply-templates select="content" />
            </body>
        </html>
    </xsl:template>
    <xsl:template match="content">
        <xsl:apply-templates select="section">
            <xsl:sort select="key('sort-key', @link-id)/order/@handle"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="section">
        Section: <xsl:value-of select="@value"/>
    </xsl:template>
</xsl:stylesheet>

Но подходите ли вы к этому с неправильной стороны? Почему бы вам не начать с прямого выбора вторых узлов, а затем использовать xsl:apply-templates для выбора соответствующего первого узла с ключом.

Попробуйте этот XSLT в качестве альтернативы

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="section" match="section" use="@link-id" />
    <xsl:template match="data">
        <html>
            <body>
                <xsl:apply-templates select="datasource/entry" />
            </body>
        </html>
    </xsl:template>

    <xsl:template match="entry">
        <xsl:apply-templates select="key('section', @id)" />
    </xsl:template>

    <xsl:template match="section">
        Section: <xsl:value-of select="@value"/>
    </xsl:template>
</xsl:stylesheet>
person Tim C    schedule 25.11.2013