Memproduksi baris baru di XSLT

198

Saya ingin menghasilkan baris baru untuk output teks dalam XSLT. Ada ide?

Mithil
sumber
11
Saya pikir, inilah saatnya untuk menerima jawabannya :)
Florjon

Jawaban:

240

Kode XSL berikut akan menghasilkan karakter baris baru (umpan baris):

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

Untuk pengembalian kereta , gunakan:

<xsl:text>&#xd;</xsl:text>
Florjon
sumber
7
+1: ini lebih kuat daripada yang <xsl:text>mengandung pendekatan baris baru jika Anda menggunakan apa pun yang dapat memformat ulang file XSL Anda dan mengacaukan spasi.
Ian Roberts
49

Metode favorit saya untuk melakukan ini terlihat seperti:

<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>

Lalu, setiap kali Anda ingin menampilkan baris baru (mungkin dalam csv), Anda dapat menampilkan sesuatu seperti berikut:

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

Saya telah menggunakan teknik ini ketika mengeluarkan sql dari input xml. Bahkan, saya cenderung membuat variabel untuk koma, kutipan, dan baris baru.

Nic Gibson
sumber
3
Harap perhatikan bahwa jawaban Florjon di bawah ini jauh lebih stabil daripada jawaban saya.
Nic Gibson
1
Mungkin perlu menambahkan deklarasi xml:space="preserve"ke xsl:textelemen untuk meningkatkan stabilitas, tetapi saya setuju bahwa jawaban @ Florjon mungkin lebih aman.
Flynn1179
Solusi ini memiliki kelemahan juga termasuk lekukan, yang mungkin tidak diinginkan.
wmassingham
47

Sertakan atribut Method = "teks" pada tag output xsl: dan sertakan baris baru dalam konten literal Anda di XSL pada titik yang sesuai. Jika Anda lebih suka menyimpan kode sumber XSL Anda rapi gunakan entitas di &#10;mana Anda ingin baris baru.

AnthonyWJones
sumber
31

Kamu bisa memakai: <xsl:text>&#10;</xsl:text>

lihat contohnya

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

jika Anda menulis ini dalam file mis

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

variabel ini akan menghasilkan infile baris baru sebagai:

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

IMHO tidak ada info lebih dari @Florjon memberi diperlukan. Mungkin beberapa detail kecil dibiarkan untuk memahami mengapa kadang-kadang itu tidak berhasil bagi kita.

Pertama-tama, &#xa(hex) atau &#10(dec) di dalam a <xsl:text/>akan selalu berfungsi, tetapi Anda mungkin tidak melihatnya.

  1. Tidak ada baris baru dalam markup HTML. Menggunakan yang sederhana <br/>akan baik-baik saja. Kalau tidak, Anda akan melihat ruang putih. Melihat sumber dari browser akan memberi tahu Anda apa yang sebenarnya terjadi. Namun, ada beberapa kasus yang Anda harapkan perilaku ini, terutama jika konsumen tidak secara langsung browser. Misalnya, Anda ingin membuat halaman HTML dan melihat strukturnya diformat dengan baik dengan baris dan id kosong sebelum menyajikannya ke browser.
  2. Ingat di mana Anda harus menggunakan disable-output-escapingdan di mana Anda tidak. Ambil contoh berikut ini di mana saya harus membuat xml dari yang lain dan mendeklarasikan DTD-nya dari stylesheet.

Versi pertama tidak luput dari karakter (default untuk xsl: teks)

<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>

dan inilah hasilnya:

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

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

Oke, itu sesuai dengan yang kita harapkan, melarikan diri dilakukan agar karakter yang kita gunakan ditampilkan dengan benar. Memformat bagian XML di dalam simpul akar ditangani oleh ident="yes". Tetapi dengan melihat lebih dekat kita melihat bahwa karakter baris baru &#xatidak lolos dan diterjemahkan sebagaimana adanya, melakukan double linefeed! Saya tidak punya penjelasan tentang ini, akan baik untuk diketahui. Siapa saja?

Versi kedua tidak luput dari karakter sehingga mereka menghasilkan apa yang dimaksudkan untuk mereka. Perubahan yang dilakukan adalah:

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

dan inilah hasilnya:

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

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

dan itu akan baik-baik saja. Baik cr dan lf ditampilkan dengan benar.

  1. Jangan lupa kita bicarakan nl, bukan crlf( nl=lf). Upaya pertama saya adalah hanya menggunakan cr: &#xddan sementara xml output divalidasi oleh DOM dengan benar.

Saya melihat xml rusak:

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

Parser DOM mengabaikan karakter kontrol tetapi yang diberikan tidak. Aku menghabiskan beberapa waktu menabrak kepalaku sebelum aku menyadari betapa konyolnya aku tidak melihat ini!

Sebagai catatan, saya menggunakan variabel di dalam tubuh dengan kedua CRLF hanya untuk memastikan 100% itu akan bekerja di mana-mana.

Lalu
sumber
4

Saya menambahkan DOCTYPEarahan yang Anda lihat di sini:

<?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">

Ini memungkinkan saya untuk menggunakan &nl;alih-alih &#xa;menghasilkan baris baru dalam output. Seperti solusi lain, ini biasanya ditempatkan di dalam <xsl:text>tag.

Sam Harwell
sumber
3

Anda dapat mencoba,

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

Itu akan berhasil.

itzmebibin
sumber
2

Saya kedua metode Nic Gibson, ini selalu favorit saya:

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

Namun saya telah menggunakan tugas Ant <echoxml> untuk membuat stylesheet dan menjalankannya terhadap file. Tugas akan melakukan templat nilai atribut, misalnya $ {DSTAMP}, tetapi juga akan memformat ulang xml Anda, jadi dalam beberapa kasus, referensi entitas lebih disukai.

<xsl:variable name='nl'><xsl:text>&#xa;</xsl:text></xsl:variable>
Hank Ratzesberger
sumber
3
Jika Anda menggunakan variabel, akan lebih baik menggunakan selectbukan xsl:text. Contoh: <xsl:variable name="nl" select="'&#xA;'"/>Dengan begitu Anda tidak membuat RTF yang tidak perlu (fragmen pohon hasil).
Daniel Haley
2

Saya telah menemukan perbedaan antara baris baru <xsl:text>literal dan baris baru literal &#xA;.

Sementara baris baru literal bekerja dengan baik di lingkungan saya (menggunakan Saxon dan prosesor Java XSLT default) kode saya gagal ketika dijalankan oleh grup lain yang berjalan di lingkungan .NET.

Mengubah ke entitas ( &#xA;) membuat kode pembuatan file saya berjalan secara konsisten pada Java dan .NET.

Juga, baris baru literal rentan untuk diformat ulang oleh IDE dan secara tidak sengaja dapat hilang ketika file tersebut dikelola oleh seseorang 'yang tidak tahu'.

Agnes
sumber
2

Aku sudah melihat dari pengalaman saya yang memproduksi baris baru DALAM sebuah <xsl:variable>klausul tidak bekerja. Saya mencoba melakukan sesuatu seperti:

<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>

Apa pun yang saya coba masukkan ke dalam "baris baru" ( <xsl:text>simpul kosong ) tidak berfungsi (termasuk sebagian besar saran sederhana di halaman ini), belum lagi fakta bahwa HTML tidak akan berfungsi di sana, jadi akhirnya saya harus membaginya menjadi 2 variabel, memanggil mereka di luar <xsl:variable>ruang lingkup dan menempatkan sederhana di <br/>antara mereka, yaitu:

<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>

Ya, saya tahu, itu bukan solusi yang paling canggih tetapi berhasil, hanya berbagi pengalaman frustrasi saya dengan XSL;)

ShayLivyatan
sumber
2

Saya tidak bisa hanya menggunakan <xsl:text>&#xa;</xsl:text>pendekatan itu karena jika saya memformat file XML menggunakan XSLT entitas akan hilang. Jadi saya harus menggunakan sedikit lebih banyak tentang pendekatan menggunakan variabel

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

tambahkan saja tag ini:

<br/>

ini bekerja untuk saya;).

Ionut Ionete
sumber
7
Pertanyaannya adalah tentang keluaran teks. Solusi Anda hanya akan berfungsi jika hasilnya diterjemahkan sebagai HTML.
oberlies