Ich bin ein ziemlich starker OOP-Programmierer, also habe ich ein wenig Mühe herauszufinden, wie XSLT als funktionale Sprache "denkt".(XSLT) Wie rekursiv durchlaufen Sie die gleiche Liste für jedes Element in der Liste?
Die tatsächliche Daten, die ich mit gerade arbeite ist empfindlich, so stattdessen nehmen wir an, ich eine XML-Liste von <albums>
haben, die enthalten ein <artist>
, <songs>
und jeder Song kann oder nicht <guest_artist>
haben.
Etwa so etwas wie diese:
<album>
<album_name>First One</album_name>
<artist_name>SomeGuy</artist_name>
<song>
<song_name>Somebody</song_name>
<guest_artist>SomebodyElse</guest_artist>
</song>
...
</album>
Mein Ziel ist es, eine CSV-Textdatei aller <guest_artist>
, die auch die primären Künstler auf einer anderen <album>
, und das Album, in dem sie erscheinen als Gast zu produzieren .
wie folgt aussehen Die Ausgabe sollte:
Guest Artist Name,Album on which they were a Guest
SombodyElse,First One
Mein erster Ansatz war zu <for-each>
über jeden /album/guest_artist
. Speichern Sie zunächst den Namen des Gastkünstlers und dann innerhalb dieser Schleife erneut <for-each>
über jede ../album/artist_name
und überprüfen Sie, ob die gespeicherte Variable mit einem der Künstlernamen übereinstimmt. In der inneren Schleife, wenn es eine Übereinstimmung gab, schreibe ich eine Zeile aus.
Etwa so:
<xsl:variable name="linefeed" select="'
'"/>
<xsl:template match="/">
<!-- Header Row Begins -->
<xsl:textGuest Artist Name,Album on which they were a Guest</xsl:text>
<xsl:value-of select="$linefeed"/>
<!-- Data Row Begins -->
<xsl:for-each select="/album/song/guest_artist">
<xsl:variable name="guest_name" select="guest_artist"/>
<xsl:variable name="this_album_name" select="../album_name"/>
<xsl:for-each select="../../album">
<xsl:if test="$guest_name=artist_name">
<xsl:value-of select="album/song/guest_artist"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$this_album_name"/>
<xsl:value-of select="$linefeed"/>
</xsl:if>
</xsl:for-each>
<!-- Data Row End -->
</xsl:template>
(Ich bin nicht besorgt über Duplikate, aber wenn ich die Grundlagen herausfinden kann, dann kann ich das Problem selbst lösen..)
Dies erzeugt seltsames Ergebnisse. Es scheint zunächst alle Gastkünstler aufzulisten, dann ein Komma, dann alle Albumnamen, dann einen Zeilenvorschub.
Ich frage nicht nach dem Code (Pseudo-Code, vielleicht). Vielmehr verstehe ich einfach nicht die Funktionen von XSLT, die ich untersuchen muss, um dies zu erreichen. Es scheint wie für-jeder Loops verhalten sich nicht so, wie ich es von ihnen erwarte. Es ist auch nicht klar, wie der Umfang gehandhabt wird. Ich vermute, dass <templates>
wird nützlich sein, aber ich habe eine harte Zeit herauszufinden, was sie tun, und wie.
Ich habe den W3-Schulkurs und einige andere Tutorials über XSL durchlaufen, aber sie scheinen diese Besonderheiten nicht zu berücksichtigen.
Irgendwelche Vorschläge?
Dieser Code sieht sehr verfahrenstechnisch aus.Die meisten erfahrenen XSLT-Benutzer würden hier Vorlagenregeln anstelle von for-each-Schleifen verwenden. Und das 'xsl: if' direkt in' xsl: for-each' sollte eigentlich ein Prädikat sein: '
Übrigens habe ich hier den Begriff "for-each loops" verwendet, den Martin in seiner gelöschten Antwort kritisiert. Er hat recht: "loop" ist loses Gespräch. Korrekterweise ist es ein funktionaler Mapping-Operator, der eine Eingabesequenz einer Ausgabesequenz zuordnet. Der Hauptunterschied besteht darin, dass die Reihenfolge der Auswertung einer "Schleife" definiert ist, wohingegen ein Abbildungsoperator die Elemente in der Eingabesequenz in beliebiger Reihenfolge oder parallel verarbeiten kann. –
Das sind hilfreiche Informationen. Eines der Probleme, die ich lösen möchte, ist die schnellere Verarbeitung einer großen Datenmenge. Es ist wahrscheinlich, dass ein erfahrenerer XSL-Benutzer bereits wissen würde, dass dieser Ansatz grundlegend beeinträchtigt ist. – Matt