XPath 1.0 Порядок возвращаемых атрибутов в UNION - PullRequest
6 голосов
/ 06 января 2012
<merge>
    <text>
        <div begin="A"   end="B" />
        <div begin="C"   end="D" />
        <div begin="E"   end="F" />
        <div begin="G"   end="H" />
    </text>
</merge>

Мне нужен UNIONed набор узлов атрибутов в порядке A, B, C, D, E, F, G, H, и это будет работать:

/merge/text/div/@begin | /merge/text/div/@end

, но только если каждый @begin предшествует каждому @end, поскольку оператор UNION должен возвращать узлы в порядке документа. (Да?)

Мне нужно, чтобы набор узлов был в том же порядке, даже если атрибуты появляются в документе в другом порядке, как здесь:

<merge>
    <text>
        <div end="B"   begin="A" />
        <div begin="C" end="D"   />
        <div end="F"   begin="E" />
        <div begin="G" end="H"   />
    </text>
</merge>

То есть мне нужно, чтобы элементы следовали порядку документа, но атрибуты в каждом элементе следовали определенному порядку (указанному или алфавитному по имени атрибута).

1 Ответ

7 голосов
/ 06 января 2012

Это просто невозможно в чистом XPath. Прежде всего, атрибуты в XML неупорядочены. Из рекомендации XML 1.0 :

Обратите внимание, что порядок спецификаций атрибутов в стартовом теге или тег пустого элемента не имеет значения.

Движок XPath может считывать и хранить их в порядке их появления в документе, но с точки зрения спецификации это просто счастливое совпадение, на которое нельзя положиться.

Во-вторых, XPath не имеет функции сортировки. Поэтому лучше всего отсортировать элементы на вашем главном языке (например, XSLT или PL общего назначения) после их выбора.

Вот как отсортировать эти атрибуты по значению в XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:apply-templates
            select="/merge/text/div/@*[name()='begin' or name()='end']">
            <xsl:sort select="."/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

Обратите внимание, что я также объединил ваши два выражения в одно.

Редактировать: Используйте следующее для вывода пар начала / конца в порядке документа (как описано в комментариях):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="div">
        <xsl:value-of select="concat(@begin, @end)"/>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...