XSLT: Wie kann ich leere Elemente von meinem Ergebnis ausschließen?

8

Ich habe ein ziemlich kompliziertes xslt-Blatt, das mit Hilfe von Templates ein XML-Format in ein anderes konvertiert. In der resultierenden XML-Datei müssen jedoch alle leeren Elemente ausgeschlossen werden. Wie ist das gemacht?

So sieht das Basis-XSLT aus:

%Vor%

Was muss hinzugefügt werden, damit leere Elemente weggelassen werden?

Zum Beispiel ein Ausschnitt aus dem resultierenden xml:

%Vor%

Das muss wirklich sein:

%Vor%

Mit anderen Worten: Leere Elemente sollten weggelassen werden.

    
Fedor Steeman 24.04.2010, 21:21
quelle

4 Antworten

11

Der angegebene (partielle) XSLT-Code veranschaulicht gut ein XSLT-Antipattern. Versuchen Sie fast immer, die Verwendung von <xsl:for-each> zu vermeiden.

Im Folgenden finden Sie ein XML-Beispieldokument und eine Transformation, die alle Knoten mit Ausnahme der "leeren" Elemente kopiert. Hier mit "leer" meinen wir entweder kinderlos oder mit einem Kind, das nur einen knotenfreien Kindknoten hat.

XML-Dokument :

%Vor%

Transformation :

%Vor%

Ergebnis:

%Vor%

Beachten Sie :

  1. Die Verwendung der Identitätsregel .

  2. Wie überschreiben wir die Identitätsregel mit einer Vorlage, die nur mit "leeren" Elementen übereinstimmt. Da diese Vorlage nichts tut (hat keinen Körper), werden die "leeren" Elemente nicht kopiert ("gelöscht").

Das Verwenden und Überschreiben der Identitätsregel ist das wichtigste XSLT-Entwurfsmuster.

    
Dimitre Novatchev 24.04.2010, 23:04
quelle
1

Dies ist wahrscheinlich der einfachste Weg:

%Vor%

Wenn Sie die Kontrolle über die XML-Generierung haben, fügen Sie den Stammknoten nicht hinzu, wenn keine untergeordneten Elemente vorhanden sind. Unabhängig davon, wie Sie sich entscheiden, XSL ist ziemlich ausführlich.

    
ChaosPandion 24.04.2010 21:38
quelle
0

Es gibt einige knifflige Fälle, in denen Dimitres Antwort (die sicherlich der richtige Ansatz ist) sich unerwartet verhalten könnte. Zum Beispiel, wenn Sie Ihre XSLT umstrukturiert haben, um das Identitätsmuster zu verwenden (was Sie sollten), und Sie haben eine Vorlage wie folgt erstellt:

%Vor%

Die Transformation kann weiterhin leere EdiActivevehicle -Elemente erstellen, wenn TransportShiftNumber leer ist.

Wenn mehrere Vorlagen einem Knoten entsprechen, wird normalerweise der spezifischere ausgewählt. "Spezifischer" bedeutet in der Regel, dass Muster, die ein Prädikat haben, Muster übertreffen, die dies nicht tun. (Die eigentlichen Konfliktauflösungsregeln sind komplizierter; siehe Abschnitt 5.5 der XSLT-Empfehlung.) In diesem Fall verwenden sowohl die obige Vorlage als auch die leere Elementvorlage Prädikate, und daher haben beide die gleiche Priorität.

Der XSLT-Prozessor wird also eines von zwei Dingen tun: Er wird einen Fehler melden (das ist erlaubt, obwohl ich noch nie einen XSLT-Prozessor gesehen habe, der unfreundlich ist), oder er wählt die Vorlage aus, die zuletzt im Stylesheet.

Es gibt zwei Möglichkeiten, dies zu beheben. Legen Sie die Vorlage für leere Elementfilter am unteren Ende des Stylesheets ab oder weisen Sie ihr explizit eine Priorität zu, die höher als 0,5 ist (dies ist der Standardwert für die meisten Muster mit Prädikaten):

Ich würde wahrscheinlich letzteres tun, weil ich Stylesheets generell mit der Erwartung strukturiere, dass die Anordnung von Templates nicht von Bedeutung ist, und dass ich keine bösen Überraschungen haben möchte, wenn ich anfange, Dinge zu bewegen. Aber ich würde ganz sicher einen Kommentar dazu schreiben und mir selbst erklären: Ich habe noch nie jemanden gesehen, der eine explizite Priorität auf einer Vorlage verwendet.

    
Robert Rossney 26.04.2010 08:39
quelle
0

Ich habe mit Dimitres Lösung oben begonnen (danke!), aber ich hatte immer noch Ausgabe- oder Null-Elemente mit null Kindern wie folgt:

%Vor%

Dies scheint zu funktionieren ... noch testen.

%Vor%     
Kurt Smith 28.11.2017 01:58
quelle

Tags und Links