Підготовка нової лінії в XSLT


198

Я хочу створити новий рядок для виведення тексту в XSLT. Будь-які ідеї?


11
Я думаю, настав час прийняти відповідь :)
Флоріон

Відповіді:


240

Наступний код XSL створить новий рядок (рядок каналу):

<xsl:text>&#xa;</xsl:text>

Для повернення вагона використовуйте:

<xsl:text>&#xd;</xsl:text>

7
+1: це більш надійно, ніж <xsl:text>містить підхід до нового рядка, якщо ви використовуєте що-небудь, що може переформатувати ваш XSL-файл і поплутатися з пробілом.
Ян Робертс

49

Мій прихильний метод для цього виглядає приблизно так:

<xsl:stylesheet>

<xsl:output method='text'/>

<xsl:variable name='newline'><xsl:text>
</xsl:text></xsl:variable>

<!-- note that the layout there is deliberate -->

...

</xsl:stylesheet>

Тоді, коли ви хочете вивести новий рядок (можливо, в csv), ви можете вивести щось на зразок наступного:

<xsl:value-of select="concat(elem1,elem2,elem3,$newline)" />

Я використовував цю техніку при виведенні sql з XML введення. Насправді я схильний створювати змінні для коми, цитат та нових рядків.


3
Зауважте, що відповідь Флоріона нижче є значно стабільнішою, ніж моя.
Нік Гібсон

1
Напевно, варто додати декларацію xml:space="preserve"до xsl:textелемента для підвищення стабільності, але я погоджуюся, що відповідь @ Флоріона, ймовірно, безпечніша.
Flynn1179

Таке рішення також має недолік, включаючи будь-які відступи, що може бути небажаним.
wmassingham

47

Включіть атрибут Method = "text" у тег xsl: output та включіть нові рядки у ваш буквальний вміст у XSL у відповідних точках. Якщо ви віддаєте перевагу збереження вихідного коду свого XSL, введіть суть, &#10;де потрібно новий рядок.


31

Ви можете використовувати: <xsl:text>&#10;</xsl:text>

див. приклад

<xsl:variable name="module-info">
  <xsl:value-of select="@name" /> = <xsl:value-of select="@rev" />
  <xsl:text>&#10;</xsl:text>
</xsl:variable>

якщо ви пишете це у файлі, наприклад

<redirect:write file="temp.prop" append="true">
  <xsl:value-of select="$module-info" />
</redirect:write>

ця змінна буде створювати новий файл infile у вигляді:

commons-dbcp_commons-dbcp = 1.2.2
junit_junit = 4.4
org.easymock_easymock = 2.4

6

ІМХО не потрібно більше інформації, ніж дав @Florjon. Можливо, залишилось кілька дрібних деталей, щоб зрозуміти, чому це може не працювати для нас іноді.

Перш за все, &#xa(hex) або &#10(dec) всередині a <xsl:text/>завжди працюватиме, але ви можете цього не бачити.

  1. Немає нового рядка в розмітці HTML. Використання простого <br/>обійдеться чудово. Інакше ви побачите пробіл. Перегляд джерела з браузера скаже вам, що насправді сталося. Однак є випадки, коли ви очікуєте такої поведінки, особливо якщо споживач не є безпосередньо веб-переглядачем. Наприклад, ви хочете створити HTML-сторінку і переглянути її структуру, добре відформатовану з порожніми рядками та ідентифікаторами, перш ніж подавати її в браузер.
  2. Запам'ятайте, де вам потрібно скористатися, disable-output-escapingа де - ні. Візьміть наступний приклад, коли мені довелося створити XML з іншого та оголосити його DTD з таблиці стилів.

Перша версія уникає символів (за замовчуванням для xsl: text)

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

    <xsl:template match="/">
        <xsl:text>&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</xsl:text>
        <xsl:copy>
            <xsl:apply-templates select="*" mode="copy"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*|node()" mode="copy">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="copy"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

і ось результат:

<?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;

&#13;<Subscriptions>
    <User id="1"/>   
</Subscriptions>

Гаразд, це все, що ми очікуємо, втеча робиться так, щоб персонажі, які ми використовували, відображалися належним чином. Форматуванням частини XML всередині кореневого вузла керує ident="yes". Але при ближчому огляді ми бачимо, що персонаж нового рядка &#xaне був уникнути і перекладений так, як є, виконуючи подвійну стрічку! У мене немає пояснення з цього приводу, буде добре знати. Хтось?

Друга версія не уникає персонажів, тому вони створюють те, для чого вони призначені. Внесені зміни були:

<xsl:text disable-output-escaping="yes">&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</xsl:text>

і ось результат:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">

<Subscriptions>
    <User id="1"/>   
</Subscriptions>

і це буде добре. І cr, і lf відображаються належним чином.

  1. Не забувайте, про що ми говоримо nl, не crlf( nl=lf). Моя перша спроба полягала в тому, щоб використовувати тільки cr: &#xdі, хоча вихідний XML був перевірений DOM належним чином.

Я переглядав пошкоджений xml:

<?xml version="1.0" encoding="utf-8"?>
<Subscriptions>riptions SYSTEM "Subscriptions.dtd">
    <User id="1"/>   
</Subscriptions>

Аналіз DOM-аналізатора не врахував контрольних символів, але відображений не став. Я витратив досить багато часу, кусаючи голову, перш ніж зрозумів, наскільки дурним я цього не бачу!

Для запису я використовую змінну всередині тіла з обома CRLF лише для того, щоб бути на 100% впевненим, що вона буде працювати всюди.


4

Я додав DOCTYPEдирективу, яку ви бачите тут:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
  <!ENTITY nl "&#xa;">
]>
<xsl:stylesheet xmlns:x="http://www.w3.org/2005/02/query-test-XQTSCatalog"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

Це дозволяє мені використовувати &nl;замість того, &#xa;щоб створити новий рядок у висновку. Як і інші рішення, це зазвичай розміщується всередині <xsl:text>тегу.



2

Я другий метод Ніка Гібсона, це завжди було моїм улюбленим:

<xsl:variable name='nl'><xsl:text>
</xsl:text></xsl:variable>

Однак я використовую завдання Ant <echoxml> для створення таблиць стилів та запуску їх з файлами. Завдання виконає шаблони значень атрибутів, наприклад, $ {DSTAMP}, але також переформатує ваш xml, тому в деяких випадках посилання на сутність є кращим.

<xsl:variable name='nl'><xsl:text>&#xa;</xsl:text></xsl:variable>

3
Якщо ви використовуєте змінну, краще використовувати її selectзамість xsl:text. Приклад. <xsl:variable name="nl" select="'&#xA;'"/>Таким чином ви не створите зайвий RTF (фрагмент дерева результатів).
Даніель Хейлі

2

Я знайшов різницю між буквальними новими рядками <xsl:text>та буквальними новими рядками&#xA; .

У той час як в моєму середовищі буквально працювали нові рядки (використовуючи як Saxon, так і процесор Java XSLT за замовчуванням), мій код не вдався, коли він був виконаний іншою групою, що працює в середовищі .NET.

Зміна суб'єктів (&#xA; ), мій код генерації файлів постійно працює на Java та .NET.

Крім того, буквальні нові рядки вразливі до переформатування IDE і можуть ненавмисно загубитися, коли файл підтримується хтось "не знає".


2

Я помітив , з мого досвіду , що виробництво нової лінії ВСЕРЕДИНІ в <xsl:variable>статті не працює. Я намагався зробити щось на кшталт:

<xsl:variable name="myVar">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My value: </xsl:text>
      <xsl:value-of select="@myValue" />
      <xsl:text></xsl:text> <!--NEW LINE-->
      <xsl:text>My other value: </xsl:text>
      <xsl:value-of select="@myOtherValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<div>
  <xsl:value-of select="$myVar"/>
</div>

Все, що я намагався вкласти у цей "новий рядок" (порожній <xsl:text>вузол), просто не працювало (включаючи більшість найпростіших пропозицій на цій сторінці), не кажучи вже про те, що HTML просто не буде працювати там, тож зрештою я довелося розділити його на 2 змінні, викликати їх поза <xsl:variable>рамками і поставити <br/>між ними просту , тобто:

<xsl:variable name="myVar1">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My value: </xsl:text>
      <xsl:value-of select="@myValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<xsl:variable name="myVar2">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My other value: </xsl:text>
      <xsl:value-of select="@myOtherValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<div>
  <xsl:value-of select="$myVar1"/>
  <br/>
  <xsl:value-of select="$myVar2"/>
</div>

Так, я знаю, це не найскладніше рішення, але воно працює, просто поділяючи своє розчарування ділюсь досвідом із XSL;)


2

Я не міг просто використовувати <xsl:text>&#xa;</xsl:text>підхід, тому що якщо я відформатую файл XML за допомогою XSLT, сутність зникне. Тому мені довелося скористатися трохи більш круглим підходом щодо використання змінних

<xsl:variable name="nl" select="'&#10;'"/>
<xsl:template match="/">
    <xsl:value-of select="$nl" disable-output-escaping="no"/>
    <xsl:apply-templates select="*"/>
</xsl:template>

-4

просто додайте цей тег:

<br/>

це працює для мене;).


7
Питання стосується виведення тексту. Ваше рішення спрацює лише в тому випадку, якщо виведення буде представлено у вигляді HTML.
oberlies
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.