Produrre una nuova linea in XSLT


198

Voglio produrre una nuova riga per l'output di testo in XSLT. Qualche idea?


11
Penso che sia ora di accettare la risposta :)
Florjon,

Risposte:


240

Il seguente codice XSL produrrà un carattere newline (avanzamento riga):

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

Per un ritorno a capo , utilizzare:

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

7
+1: è più robusto dell'approccio <xsl:text>contenente una nuova riga se usi qualcosa che potrebbe riformattare il tuo file XSL e pasticciare con lo spazio bianco.
Ian Roberts,

49

Il mio metodo preferito per farlo è simile a:

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

Quindi, ogni volta che vuoi produrre una nuova riga (forse in csv) puoi produrre qualcosa di simile al seguente:

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

Ho usato questa tecnica per produrre sql dall'input xml. In realtà, tendo a creare variabili per virgole, virgolette e newline.


3
Si prega di notare che la risposta di Florjon di seguito è considerevolmente più stabile della mia.
Nic Gibson,

1
E 'probabilmente la pena di aggiungere la dichiarazione xml:space="preserve"per l' xsl:textelemento di maggiore stabilità, ma ero d'accordo che la risposta di @ Florjon è probabilmente più sicuro.
Flynn1179,

Questa soluzione ha anche l'inconveniente di includere qualsiasi rientro, che potrebbe non essere desiderabile.
wmassingham,

47

Includere l'attributo Method = "text" sul tag di output xsl: e includere le nuove righe nel contenuto letterale nell'XSL nei punti appropriati. Se si preferisce mantenere in ordine il codice sorgente della propria XSL, utilizzare l'entità in &#10;cui si desidera una nuova riga.


31

Puoi usare: <xsl:text>&#10;</xsl:text>

vedi l'esempio

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

se lo scrivi nel file ad es

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

questa variabile produrrà una nuova riga come:

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

6

Non sono necessarie più informazioni di quelle fornite da @Florjon. Forse sono rimasti alcuni piccoli dettagli per capire perché a volte potrebbe non funzionare per noi.

Prima di tutto, il &#xa(hex) o &#10(dec) all'interno di a <xsl:text/>funzionerà sempre, ma potresti non vederlo.

  1. Non esiste una nuova riga in un markup HTML. Usando un semplice<br/> andrà bene. Altrimenti vedrai uno spazio bianco. La visualizzazione della fonte dal browser ti dirà cosa è realmente successo. Tuttavia, ci sono casi in cui ti aspetti questo comportamento, soprattutto se l'utente non è direttamente un browser. Ad esempio, si desidera creare una pagina HTML e visualizzarne la struttura formattata correttamente con righe e ID vuoti prima di servirla nel browser.
  2. Ricorda dove devi usare disable-output-escapinge dove no. Prendi l'esempio seguente in cui ho dovuto creare un XML da un altro e dichiarare il suo DTD da un foglio di stile.

La prima versione sfugge ai caratteri (impostazione predefinita per xsl: testo)

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

E questo è il risultato:

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

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

Ok, fa quello che ci aspettiamo, l'escaping è fatto in modo che i personaggi che abbiamo usato siano visualizzati correttamente. La formattazione della parte XML all'interno del nodo radice è gestita da ident="yes". Ma con uno sguardo più attento vediamo che il personaggio della nuova riga &#xanon è stato evaso e tradotto così com'è, eseguendo un doppio avanzamento di riga! Non ho una spiegazione al riguardo, sarà bene saperlo. Chiunque?

La seconda versione non sfugge ai personaggi, quindi stanno producendo ciò per cui sono destinati. La modifica apportata è stata:

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

E questo è il risultato:

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

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

e andrà bene. Sia cr che lf sono resi correttamente.

  1. Non dimenticare che stiamo parlando nl, non crlf( nl=lf). Il mio primo tentativo è stato di usare solo cr: &#xde mentre l'xml di output è stato validato correttamente da DOM.

Stavo visualizzando un XML danneggiato:

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

Il parser DOM ha ignorato i caratteri di controllo ma il rendering no. Ho passato parecchio tempo a sbattere la testa prima di rendermi conto di quanto sciocco non lo vedessi!

Per la cronaca, uso una variabile all'interno del corpo con entrambi i CRLF solo per essere sicuro al 100% che funzionerà ovunque.


4

Ho aggiunto la DOCTYPEdirettiva che vedi qui:

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

Questo mi permette di usare &nl;invece di &#xa;produrre una nuova riga nell'output. Come altre soluzioni, questo viene generalmente inserito in un <xsl:text>tag.



2

Secondo il metodo di Nic Gibson, questo è sempre stato il mio preferito:

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

Tuttavia ho usato il task Ant <echoxml> per creare fogli di stile ed eseguirli su file. L'attività eseguirà modelli di valore di attributo, ad esempio $ {DSTAMP}, ma riformatterà anche il tuo xml, quindi in alcuni casi è preferibile il riferimento all'entità.

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

3
Se usi una variabile, sarebbe meglio usare selectinvece di xsl:text. Esempio: in <xsl:variable name="nl" select="'&#xA;'"/>questo modo non si crea un RTF non necessario (frammento dell'albero dei risultati).
Daniel Haley,

2

Ho trovato una differenza tra le newline <xsl:text>letterali e le newline letterali usando &#xA;.

Mentre i newline letterali funzionavano bene nel mio ambiente (usando sia Saxon che il processore Java XSLT predefinito) il mio codice falliva quando veniva eseguito da un altro gruppo in esecuzione in un ambiente .NET.

Passando alle entità ( &#xA;) il mio codice di generazione del file è stato eseguito costantemente su Java e .NET.

Inoltre, le newline letterali sono vulnerabili alla riformattazione da parte degli IDE e possono inavvertitamente perdersi quando il file viene gestito da qualcuno che non è al corrente.


2

Ho notato dalla mia esperienza che la produzione di una nuova riga INSIDE una <xsl:variable>clausola non funziona. Stavo cercando di fare qualcosa del tipo:

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

Tutto ciò che ho cercato di inserire in quella "nuova riga" (il <xsl:text>nodo vuoto ) non ha funzionato (inclusa la maggior parte dei suggerimenti più semplici in questa pagina), per non parlare del fatto che l'HTML non funzionerà lì, quindi alla fine ho ho dovuto dividerlo in 2 variabili, chiamarle al di fuori <xsl:variable>dell'ambito e mettere un semplice <br/>tra di loro, cioè:

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

Sì, lo so, non è la soluzione più sofisticata ma funziona, solo condividendo la mia esperienza di frustrazione con XSL;)


2

Non potrei semplicemente usare l' <xsl:text>&#xa;</xsl:text>approccio perché se formatto il file XML usando XSLT l'entità scompare. Quindi ho dovuto usare un approccio leggermente più circolare all'approccio usando le variabili

<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

aggiungi questo tag:

<br/>

per me funziona ;) .


7
La domanda riguarda l'output del testo. La tua soluzione funzionerebbe solo se l'output fosse reso come HTML.
oberlies,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.