Список заданного атрибута определенных дочерних элементов

У меня есть XML-код, который выглядит так

<SEARCHRESULTS>
  <FUNCTION name = "BarGraph">
    <PARAMETER name = "numList"></PARAMETER>
    <PARAMETER name = "maxValue"></PARAMETER>
    <CODE>Some code</CODE>
  </FUNCTION>
</SEARCHRESULTS>

И я хочу извлечь список имен параметров для каждой функции, пока у меня есть следующий xsl-код

<xsl:for-each select = "SEARCHRESULTS/FUNCTION">
  <ROW>
    <COL><DATA><xsl:value-of select = "@name" /></DATA></COL>
    <COL><DATA><xsl:value-of select = "PARAMETER/@name" /></DATA></COL>
    <COL><DATA><xsl:value-of select = "CODE" /></DATA></COL>
  </ROW>
</xsl:for-each>

который, конечно, возвращает имя первого параметра вместе с именем и кодом функции.

Мне нужен список всех параметров функции в текстовой строке. Разделить возврат лучше всего, но пока все имена находятся в строке, я могу разобрать ее позже.

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

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

Результирующий XML должен выглядеть так:

<ROW>
  <COL><DATA>BarGraph</DATA></COL>
  <COL><DATA>numList;maxValue</DATA></COL>
  <COL><DATA>Some code</DATA></COL>
</ROW>

Где ';' во втором столбце может быть возврат каретки или другой символ, который я могу указать

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

Ответы 4

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

Попробуйте со вторым foreach:

<xsl:template match = "/">
<xsl:for-each select = "SEARCHRESULTS/FUNCTION">
  <ROW>
    <COL>
      <DATA>
        <xsl:value-of select = "@name" />
      </DATA>
    </COL>
    <COL>
      <DATA>
        <xsl:for-each select = "PARAMETER">
          <!-- separate the names by a semicolon (do not insert a semicolon the first time -->
          <xsl:if test = "position() > 1">
            <xsl:text>;</xsl:text>
          </xsl:if>
          <xsl:value-of select = "@name" />
        </xsl:for-each>
      </DATA>
    </COL>
    <COL>
      <DATA>
        <xsl:value-of select = "CODE" />
      </DATA>
    </COL>
  </ROW>
</xsl:for-each>

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

Matt Haughton 07.01.2009 19:19
<xsl:template match = "PARAMETER">
    <xsl:value-of select = "@name" />
    <xsl:text> </xsl:text>
</xsl:template>

Заменить текущий код

  <COL><DATA><xsl:value-of select = "PARAMETER/@name" /></DATA></COL>

с участием

  <COL><DATA><xsl:apply-templates select = "PARAMETER"/></DATA></COL>

Куда идет код <xsl: template match = "PARAMETER">, будет ли он находиться выше начального <for-each>?

Matt Haughton 04.01.2009 20:35

Нет, это должен быть отдельный шаблон выше или ниже вашего «основного» шаблона (того, который соответствует '/').

Dirk Vollmar 04.01.2009 20:41

<xsl: text> </ xsl: text> просто вставляет пробел для разделения имен параметров.

Dirk Vollmar 04.01.2009 20:46

Ах, правильно ли я предполагаю, что этот код автоматически объединит все параметры в одну текстовую строку? И я мог бы заменить этот пробел, например, на возврат каретки (в некоторых параметрах будут пробелы)?

Matt Haughton 04.01.2009 20:49

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

Matt Haughton 04.01.2009 20:58

Одним из возможных преобразований, дающих требуемый результат, является следующее:

<xsl:stylesheet version = "1.0"
 xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration = "yes" indent = "yes"/>
 <!--                                              -->
    <xsl:template match = "/*">
      <TABLE>
        <xsl:apply-templates select = "*"/>
      </TABLE>
    </xsl:template>
 <!--                                              -->
    <xsl:template match = "FUNCTION">
      <ROW>
        <COL><xsl:value-of select = "@name"/></COL>
        <COL><xsl:apply-templates select = "PARAMETER"/></COL>
        <COL><xsl:apply-templates select = "CODE"/></COL>
      </ROW>
    </xsl:template>
 <!--                                              -->
<xsl:template match = "PARAMETER">
 <xsl:param name = "pDelim" select = "';'"/>
 <xsl:value-of select=
 "concat(@name,
         substring($pDelim,
                   1 div not(position() = last()))
                   )"/>
</xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к исходному XML-документу:

<SEARCHRESULTS>
    <FUNCTION name = "BarGraph">
        <PARAMETER name = "numList"></PARAMETER>
        <PARAMETER name = "maxValue"></PARAMETER>
        <CODE>Some code</CODE>
    </FUNCTION>
</SEARCHRESULTS>

Получен желаемый результат:

<TABLE>
   <ROW>
      <COL>BarGraph</COL>
      <COL>numList;maxValue</COL>
      <COL>Some code</COL>
   </ROW>
</TABLE>

Обратите внимание, что <xsl:template>, который соответствует PARAMETER, имеет параметр $pDelim, который может использоваться, чтобы указать, какой символ (или строку) использовать в качестве разделителя для списка имен параметров. По умолчанию этот разделитель имеет значение «;».

xsl: apply-templates будет вашим ответом. Все просто и элегантно.

<xsl:template match = "FUNCTION/PARAMETER">
    <xsl:if test = "position() > 1">
        <xsl:text>; </xsl:text> <!-- This is the delimiter -->
    </xsl:if>
    <xsl:value-of select = "@name" />
</xsl:template>

Тогда вместо <xsl:value-of select = "PARAMETER/@name" /> вы сделаете это:

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

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