Использование XSLT для итерации и преобразования XML в простой текст

Я новичок и все еще учусь XSLT. У меня есть простой XML-код ниже:

<?xml version = "1.0" encoding = "UTF-8"?>
<order id = "1021">
    <items>
        <item code = "11">
            <quantity>2</quantity
            <price>50</price>
        </item>
        <item code = "21">
            <quantity>1</quantity>
            <price>250</price>
        </item>
        <item code = "13">
            <quantity>4</quantity>
            <price>100</price>
        </item>
    </items>
    <status>3</status>
</order>

И я хочу написать сценарий XSLT, который преобразует его в простой текстовый массив, содержащий все коды элементов. Например, приведенный выше XML-код следует преобразовать как: [11,21,13]

Я написал следующий код XSLT:

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

    <xsl:output method = "text"/>
    <xsl:strip-space elements = "*"/>

    <!-- Template to match the root 'order' element -->
    <xsl:template match = "/order">
        <!-- Start bracket for the array -->
        <xsl:text>[</xsl:text>
        <!-- Iterate over each item -->
        <xsl:for-each select = "items/item">
            <!-- Output the code attribute -->
            <xsl:value-of select = "@code"/>
            <!-- If not the last item, add a comma and space -->
            <xsl:if test = "position() != last()">
                <xsl:text>, </xsl:text>
            </xsl:if>
        </xsl:for-each>
        <!-- End bracket for the array -->
        <xsl:text>]</xsl:text>
    </xsl:template>

</xsl:stylesheet>

Я столкнулся с проблемой перебора всех элементов. Я получаю только код первого элемента вывода: [11]

Где я ожидаю коды всех предметов, например: [11,21,13]

Пожалуйста, дайте мне знать, если кто-нибудь заметит ошибку в моем коде XSLT. Я пробовал попросить об этом чатгпт, но это не очень помогло.

В вашем XSLT нет ошибок, и он дает ожидаемый результат (за исключением пробелов после запятых) — при условии, что вы добавите недостающий > во входной XML. Как вы это тестируете?

michael.hor257k 23.05.2024 12:05

Я тестирую это на онлайн-компиляторе школ w3, а также пробовал программу на Python, которая его преобразует. Оба они дают одинаковый результат

ItsBuddy007 23.05.2024 15:31

Пожалуйста, отредактируйте вопрос и покажите полный код Python, позволяющий нам воспроизвести предполагаемый результат [11]. Я с кодом типа gist.github.com/martin-honnen/baa79449b27317d33e697a15ee2d67‌​f9 конечно получаю результат [11, 21, 13].

Martin Honnen 23.05.2024 17:24

Вы должны использовать другой код в своих тестах.

michael.hor257k 23.05.2024 18:02

Я вижу, что вы используете XSLT 1.0 (около 1999 г.). Можно ли начать использовать XSLT 2.0 или 3.0? Это значительно облегчит вашу задачу.

Yitzhak Khabinsky 23.05.2024 18:02

@YitzhakKhabinsky Ваш комментарий можно истолковать как предположение о том, что проблема вызвана каким-то недостатком в XSLT 1.0. Что, конечно, неправда.

michael.hor257k 23.05.2024 19:24

В ОП упоминается: «Я новичок и все еще учусь XSLT». Лучше начинать изучение XSLT с версии выше 1.0.

Yitzhak Khabinsky 23.05.2024 19:32

@YitzhakKhabinsky Возможно, но это не имеет никакого отношения к вопросу. Было бы лучше отложить ваш совет до тех пор, пока не будет решена текущая проблема.

michael.hor257k 23.05.2024 20:26

Я допустил глупую ошибку в XML-коде: мне не хватает >, как заметил @michael.hor257k <item code = "11"> <quantity>2</quantity <price>50</price> </item>

ItsBuddy007 24.05.2024 12:45

Но любой соответствующий процессор выдал бы ошибку вместо того результата, который вы утверждаете.

michael.hor257k 24.05.2024 13:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш XSLT 1.0 отлично работает.

Для сравнения см. ниже, насколько проще это реализовать в XSLT 2.0 и более поздних версиях.

В XSLT 2.0 <xsl:value-of> был улучшен и теперь имеет атрибут разделителя.

XSLT, 2-е издание, Дуг Тидвелл

  • XSLT 1.0 стал рекомендацией W3C в ноябре 1999 года.
  • XSLT 2.0 стал рекомендацией W3C в январе 2007 года.
  • XSLT 3.0 стал рекомендацией W3C в июне 2017 года.

Для справки: XSLT

Входной XML

<?xml version = "1.0" encoding = "UTF-8"?>
<order id = "1021">
    <items>
        <item code = "11">
            <quantity>2</quantity>
            <price>50</price>
        </item>
        <item code = "21">
            <quantity>1</quantity>
            <price>250</price>
        </item>
        <item code = "13">
            <quantity>4</quantity>
            <price>100</price>
        </item>
    </items>
    <status>3</status>
</order>

XSLT 1.0

<?xml version = "1.0"?>
<xsl:stylesheet version = "1.0"
                xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
    <xsl:output method = "text"/>
    <xsl:strip-space elements = "*"/>

    <!-- Template to match the root 'order' element -->
    <xsl:template match = "/order">
        <!-- Start bracket for the array -->
        <xsl:text>[</xsl:text>
        <!-- Iterate over each item -->
        <xsl:for-each select = "items/item">
            <!-- Output the code attribute -->
            <xsl:value-of select = "@code"/>
            <!-- If not the last item, add a comma and space -->
            <xsl:if test = "position() != last()">
                <xsl:text>, </xsl:text>
            </xsl:if>
        </xsl:for-each>
        <!-- End bracket for the array -->
        <xsl:text>]</xsl:text>
    </xsl:template>
</xsl:stylesheet>

XSLT 2.0

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

    <xsl:template match = "/">
        <xsl:text>[</xsl:text>
        <xsl:value-of select = "order/items/item/@code"
                      separator = ", "/>
        <xsl:text>]</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Выход

[11, 21, 13]

Поскольку вы с таким энтузиазмом стремитесь быть в курсе последних версий XSLT, вы могли бы перейти на XSLT 3.0 и получить желаемый результат, используя только <xsl:sequence select = "array{/order/items/item/number(@code)}"/>. Но все это еще не имеет никакого отношения к вопросу.

michael.hor257k 23.05.2024 22:38

@michael.hor257k, я полностью с тобой согласен. Подождем отзывов ОП.

Yitzhak Khabinsky 23.05.2024 22:44

Спасибо за ссылку на XSLT 2.0, а также на XSLT 3.0 @michael.hor257k. Я считаю, что с новыми версиями язык стал проще. Однако в рамках моего курса мы должны изучать и работать с XSLT 1.0. Поэтому я пытался изучить и практиковать это.

ItsBuddy007 24.05.2024 12:46

Вы правильно написали XML-код, добавив недостающий >, который вызывал проблемы при выводе.

ItsBuddy007 24.05.2024 12:47

Другие вопросы по теме