Erstellen einer neuen Zeile in XSLT


197

Ich möchte eine neue Zeile für die Textausgabe in XSLT erstellen. Irgendwelche Ideen?


11
Ich denke, es ist Zeit, die Antwort zu akzeptieren :)
Florjon

Antworten:


239

Der folgende XSL-Code erzeugt ein Zeilenumbruchzeichen (Zeilenvorschub):

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

Verwenden Sie für einen Wagenrücklauf :

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

7
+1: Dies ist robuster als <xsl:text>ein Newline-Ansatz, wenn Sie etwas verwenden, das Ihre XSL-Datei neu formatieren und mit dem Leerzeichen herumspielen könnte.
Ian Roberts

49

Meine bevorzugte Methode dafür sieht ungefähr so ​​aus:

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

Wenn Sie dann eine neue Zeile ausgeben möchten (möglicherweise in CSV), können Sie Folgendes ausgeben:

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

Ich habe diese Technik bei der Ausgabe von SQL aus XML-Eingaben verwendet. Tatsächlich neige ich dazu, Variablen für Kommas, Anführungszeichen und Zeilenumbrüche zu erstellen.


3
Bitte beachten Sie, dass Florjons Antwort unten wesentlich stabiler ist als meine.
Nic Gibson

1
Es lohnt sich wahrscheinlich, die Deklaration xml:space="preserve"zu dem xsl:textElement hinzuzufügen , um die Stabilität zu erhöhen, aber ich würde zustimmen, dass die Antwort von @ Florjon wahrscheinlich sicherer ist.
Flynn1179

Diese Lösung hat den Nachteil, dass auch Einrückungen enthalten sind, die möglicherweise nicht wünschenswert sind.
Wmassingham

47

Fügen Sie das Attribut Method = "text" in das xsl: output-Tag ein und fügen Sie an den entsprechenden Stellen Zeilenumbrüche in Ihren Literalinhalt in der XSL ein. Wenn Sie den Quellcode Ihres XSL lieber aufgeräumt halten &#10;möchten, verwenden Sie die Entität, in der Sie eine neue Zeile wünschen.


30

Sie können verwenden: <xsl:text>&#10;</xsl:text>

siehe das Beispiel

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

Wenn Sie dies in eine Datei schreiben, z

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

Diese Variable erzeugt eine neue Zeileninfile wie folgt:

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

6

IMHO werden nicht mehr Infos als von @Florjon angegeben benötigt. Vielleicht bleiben einige kleine Details übrig, um zu verstehen, warum es bei uns manchmal nicht funktioniert.

Zuallererst funktioniert das &#xa(hex) oder &#10(dec) in einem <xsl:text/>immer, aber Sie können es möglicherweise nicht sehen.

  1. In einem HTML-Markup ist kein Zeilenumbruch enthalten. Die Verwendung eines einfachen <br/>wird gut tun. Andernfalls sehen Sie einen Leerraum. Wenn Sie die Quelle im Browser anzeigen, erfahren Sie, was wirklich passiert ist. Es gibt jedoch Fälle, in denen Sie dieses Verhalten erwarten, insbesondere wenn der Verbraucher kein direkter Browser ist. Sie möchten beispielsweise eine HTML-Seite erstellen und deren Struktur mit leeren Zeilen und IDents formatieren, bevor Sie sie dem Browser bereitstellen.
  2. Denken Sie daran, wo Sie verwenden müssen disable-output-escapingund wo nicht. Nehmen Sie das folgende Beispiel, in dem ich eine XML aus einer anderen erstellen und ihre DTD aus einem Stylesheet deklarieren musste.

Die erste Version entgeht den Zeichen (Standard für 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>

und hier ist das Ergebnis:

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

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

Ok, es macht das, was wir erwarten. Es wird ein Escape-Vorgang ausgeführt, damit die von uns verwendeten Zeichen korrekt angezeigt werden. Die XML-Teilformatierung innerhalb des Stammknotens wird von übernommen ident="yes". Bei näherer Betrachtung sehen wir jedoch, dass das Newline-Zeichen &#xanicht maskiert und so wie es ist übersetzt wurde und einen doppelten Zeilenvorschub ausführt! Ich habe keine Erklärung dazu, wird gut zu wissen sein. Jemand?

Die zweite Version entgeht den Charakteren nicht und produziert das, wofür sie bestimmt sind. Die vorgenommene Änderung war:

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

und hier ist das Ergebnis:

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

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

und das wird ok sein. Sowohl cr als auch lf werden ordnungsgemäß gerendert.

  1. Vergiss nicht, dass wir darüber reden nl, nicht crlf( nl=lf). Mein erster Versuch war, nur cr: zu verwenden, &#xdund während die Ausgabe-XML von DOM ordnungsgemäß validiert wurde.

Ich habe eine beschädigte XML-Datei angezeigt:

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

Der DOM-Parser ignorierte Steuerzeichen, der gerenderte jedoch nicht. Ich habe einige Zeit damit verbracht, mir den Kopf zu stoßen, bevor mir klar wurde, wie dumm ich das nicht sah!

Für die Aufzeichnung verwende ich eine Variable im Körper mit beiden CRLF, nur um 100% sicher zu sein, dass sie überall funktioniert.


4

Ich habe die DOCTYPERichtlinie hinzugefügt, die Sie hier sehen:

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

Dies ermöglicht es mir, &nl;anstatt &#xa;eine neue Zeile in der Ausgabe zu erzeugen. Wie bei anderen Lösungen wird dies normalerweise in einem <xsl:text>Tag platziert.


3

Du kannst es versuchen,

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

Es wird klappen.


2

Ich habe Nic Gibsons Methode unterstützt, das war immer mein Favorit:

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

Ich habe jedoch die Ant-Task <echoxml> verwendet, um Stylesheets zu erstellen und sie für Dateien auszuführen. Die Aufgabe erstellt Attributwertvorlagen, z. B. $ {DSTAMP}, formatiert jedoch auch Ihre XML-Datei neu. In einigen Fällen ist daher die Entitätsreferenz vorzuziehen.

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

3
Wenn Sie eine Variable verwenden, ist es besser, selectanstelle von zu verwenden xsl:text. Beispiel: Auf <xsl:variable name="nl" select="'&#xA;'"/>diese Weise erstellen Sie kein unnötiges RTF (Ergebnisbaumfragment).
Daniel Haley

2

Ich habe einen Unterschied zwischen wörtlichen Zeilenumbrüchen in <xsl:text>und wörtlichen Zeilenumbrüchen mit festgestellt &#xA;.

Während wörtliche Zeilenumbrüche in meiner Umgebung einwandfrei funktionierten (sowohl mit Saxon als auch mit dem Standard-Java XSLT-Prozessor), schlug mein Code fehl, als er von einer anderen Gruppe ausgeführt wurde, die in einer .NET-Umgebung ausgeführt wurde.

Durch das Ändern von entity ( &#xA;) wurde mein Dateierzeugungscode sowohl auf Java als auch auf .NET konsistent ausgeführt.

Außerdem sind wörtliche Zeilenumbrüche anfällig für eine Neuformatierung durch IDEs und können versehentlich verloren gehen, wenn die Datei von jemandem verwaltet wird, der sich nicht auskennt.


2

Ich habe aus meiner Erfahrung heraus festgestellt, dass das Erstellen einer neuen Zeile INNERHALB einer <xsl:variable>Klausel nicht funktioniert. Ich habe versucht, etwas zu tun wie:

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

Alles, was ich versucht habe, in diese "neue Zeile" (den leeren <xsl:text>Knoten) einzufügen, hat einfach nicht funktioniert (einschließlich der meisten einfacheren Vorschläge auf dieser Seite), ganz zu schweigen von der Tatsache, dass HTML dort einfach nicht funktioniert, also habe ich es irgendwann getan musste es in 2 Variablen aufteilen, sie außerhalb des <xsl:variable>Gültigkeitsbereichs aufrufen und eine einfache <br/>dazwischen setzen, dh:

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

Ja, ich weiß, es ist nicht die ausgefeilteste Lösung, aber es funktioniert, nur meine Frustrationserfahrung mit XSLs zu teilen;)


2

Ich konnte den <xsl:text>&#xa;</xsl:text>Ansatz nicht einfach verwenden, da die Entität verschwindet, wenn ich die XML-Datei mit XSLT formatiere. Also musste ich einen etwas runderen Ansatz mit Variablen verwenden

<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

füge einfach dieses Tag hinzu:

<br/>

Für mich geht das ;) .


7
Die Frage betrifft die Textausgabe. Ihre Lösung würde nur funktionieren, wenn die Ausgabe als HTML gerendert würde.
Oberlies
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.