Форматирование текста XML для преобразования XSL

#xml #xslt

#xml #xslt

Вопрос:

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

 <root>
<level_one>
My first line of text on level_one
<level_two>
My only line of text on level_two
</level_two>
My second line of text on level_one
</level_one>
</root>
  

 <xsl:template match="level_one">
<xsl:value-of select="text()"/>
<br/>
<xsl:apply-templates select="level_two"/>
</xsl:template>

<xsl:template match="level_two">
<xsl:value-of select="text()"/>
<br/>
</xsl:template>
  

В нынешнем виде вывод (измененный здесь для чтения) при выполнении вышеописанного является

 My first line of text on level_one
<br/>
My only line of text on level_two
<br/>
  

Мне не хватает второй строки текста на level_one. Итак, меня интересуют две вещи.

  1. Допустим ли XML? Из того, что я знаю, ответ «да», но я ошибаюсь?
  2. Как я могу изменить XSL, чтобы получить вторую строку (или даже больше строк в моем случае, чем я показал)?

Спасибо

Комментарии:

1. Я думаю, что это не очень хороший xml-стиль для размещения вложенного тега между текстом

2. Хороший вопрос, 1. Смотрите мой ответ для объяснения причины этой проблемы и для простого и естественного решения.

Ответ №1:

Используйте стандартную модель обработки XSLT рекурсивного спуска с использованием xsl:apply-templates.

 <xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()">
<xsl:value-of select="."/>
<br/>
</xsl:template>
  

Использование <xsl:value-of select="text()"/> — плохая новость. В XSLT 1.0 отображается только первый текстовый узел (как вы обнаружили). В XSLT 2.0 отображаются все дочерние текстовые узлы, разделенные пробелом, но это, вероятно, не то, что вы хотите, потому что первое и третье предложения будут выводиться перед вторым. (На самом деле вы не сказали точно, какой вывод вы хотите, поэтому мне приходится догадываться.)

Ответ №2:

Даже без сопоставления с шаблоном text() вы можете вывести два text() дочерних узла текущего узла ( level_one ), заменив:

 <xsl:value-of select="text()"/>
  

с:

 <xsl:copy-of select="text()"/>
  

В XSLT 1.0 очень важно знать, что <xsl:value-of select="$someNodeSet"/> в XSLT создается строковое значение только первого узла (в порядке документа) из $someNodeSet набора узлов.

С другой стороны:

 <xsl:copy-of select="$someNodeSet"/>
  

копирует все узлы, содержащиеся в $someNodeSet .

Комментарии:

1. 1 Отличное объяснение использования значения-of и копирования-of в XSLT 1.0.

Ответ №3:

Допустим ли XML? Из того, что я знаю, ответ «да», но я ошибаюсь?

Да, ваш XML допустим. Также, вопреки комментарию выше, нет ничего плохого в том, чтобы иметь смешанный контент (текст и элементы, смешанные вместе) в XML. Все зависит от контекста и того, как используется XML. Например, было бы практически невозможно создавать технические руководства без смешанного контента. (Хорошим примером являются ссылочные элементы, смешанные с текстом в элементах абзаца.)

Как я могу изменить XSL, чтобы получить вторую строку (или даже больше строк в моем случае, чем я показал)?

Я не совсем уверен, чего вы пытаетесь достичь, но причина, по которой вы не видите вторую строку текста, заключается в том, что вы сопоставляете только первую строку с первой <xsl:value-of select="text()"/> .

Я не уверен, сработает ли это с вашим полным набором XML-данных, но вы могли бы заменить оба шаблона, level_one и level_two , одним шаблоном, который соответствует всем text() :

   <xsl:template match="text()">
    <xsl:value-of select="."/>
    <br/>
  </xsl:template>
  

Это приводит к следующему результату:

   My first line of text on level_one
  <br/>
  My only line of text on level_two
  <br/>
  My second line of text on level_one
  <br/>
  

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

   <xsl:template match="level_one/text()|level_two/text()">
    <xsl:value-of select="."/>
    <br/>
  </xsl:template>
  

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

Надеюсь, это поможет.

Комментарии:

1. Да, это очень помогло! Я избегал общего шаблона text (), чтобы я мог лучше управлять структурой и выводом. В итоге я использовал шаблон general text (), но поставил условие для проверки родительского элемента, чтобы он вступал в силу только там, где мне это нужно.