Как объединить и очистить несколько тегов в одном? - PullRequest
0 голосов
/ 26 апреля 2020

Я ломаю голову и не могу решить эту проблему элегантным способом с помощью XSL. У меня есть элемент XML с вложенными тегами, создающими заголовок. Для отображения это хорошо. Но при экспорте в поставщика для публикации в Интернете возникает проблема.

См. Элемент:

<headline>
  <ln id="U20777523148AQE">FOOD PARCEL</ln>
  <ln id="U20777523148kHH">LOOTING</ln>
  <ln id="U20777523148buE">HITS THE POOR</ln>
</headline>

Идеальное решение должно выглядеть так:

<headline>
  <ln>FOOD PARCEL LOOTING HITS THE POOR</ln>
</headline>

Конечно, количество строк (ln) также может отличаться. От одной строки до нескольких, как показано в примере. Некоторая помощь или указатели были бы очень признательны.

Вот пример не очень хорошей идеи, которая у меня была.

<headline>
  <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[1]/text()"/><xsl:text> </xsl:text>
  <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[2]/text()"/><xsl:text> </xsl:text>
  <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[3]/text()"/><xsl:text> </xsl:text>
  <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[4]/text()"/><xsl:text> </xsl:text>
  <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[5]/text()"/><xsl:text> </xsl:text>
</headline>

Еще немного фона - см. Текущий XSL, в котором преобразование используется.

<doc>
    <story>
        <grouphead>
            <overhead>
                <ln>
                    <xsl:value-of select="/doc/story/grouphead[1]/overhead/ln/text()"/>
                </ln>
            </overhead>
            <headline>
                <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[1]/text()"/>
                <xsl:text> </xsl:text>
                <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[2]/text()"/>
                <xsl:text> </xsl:text>
                <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[3]/text()"/>
                <xsl:text> </xsl:text>
                <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[4]/text()"/>
                <xsl:text> </xsl:text>
                <xsl:copy-of select="/doc/story/grouphead[1]/headline/ln[5]/text()"/>
                <xsl:text> </xsl:text>
            </headline>
            <subhead>
                <ln>
                    <xsl:value-of select="/doc/story/grouphead[1]/subhead/ln/text()"/>
                </ln>
            </subhead>
        </grouphead>
        <text>
            <byline>
                <author>
                    <name>
                        <xsl:value-of select="/doc/story/text/byline/author/name/text()"/>
                    </name>
                    <description>
                        <xsl:value-of select="/doc/story/text/byline/author/description/text()"/>
                    </description>
                </author>
            </byline>
        </text>
    </story>
</doc>

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Ваша цель может быть легко достигнута путем получения строкового значения из headline,

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

, а затем очистка пробелов с помощью нормализуют-пространство () .

XSLT, все версии

Этот XSLT,

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

  <xsl:template match="headline">
    <xsl:copy>
      <ln>
        <xsl:value-of select="normalize-space()"/>
      </ln>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

, примененный к вашему входу XML, дает этот вывод XML,

<?xml version="1.0"?>
<headline>
  <ln>FOOD PARCEL LOOTING HITS THE POOR</ln>
</headline>

по запросу.


Примечание: Этот подход будет работать, даже если за пределами ln есть дополнительный текст (например, запятые или другие знаки пунктуации); этот метод обычно используется для элементов со смешанным содержимым в роли headline. С другой стороны, не будет вводить интервал между ln элементами, если их изначально не было. Если вы введете sh пробел, который будет введен между ln элементами независимо от того, он существует в источнике XML, см. ответ Себастьяна . [Спасибо, @ michael.hor257k, за за указание на эту проблему .]

0 голосов
/ 26 апреля 2020

Если ваши процессоры поддерживают XSLT 2.0:

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="headline">
      <xsl:copy>
          <ln><xsl:value-of select="ln"/></ln>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Если он поддерживает только XSLT 1.0:

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="headline">
    <xsl:copy>
      <ln>
        <xsl:for-each select="ln">
          <xsl:value-of select="."/>
            <xsl:if test="position()!=last()"> <!-- Add space if not last element -->
              <xsl:value-of select="' '"/>
            </xsl:if>
        </xsl:for-each>
      </ln>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Смотрите, как это работает здесь: https://xsltfiddle.liberty-development.net/jxDiMBZ

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