Wie wähle ich die letzten N-Elemente mit XPath aus?

Ich unterstütze eine Website, die Content XML generiert, die dann mit XSLT in Webseiten übersetzt wird. Ich wurde gebeten, ein neues Stylesheet zu erstellen, das die Ausgabe der "Archiv"-Seite in Atom für die Syndizierung umwandeln wird. Das Problem, auf das ich gestoßen bin, ist, dass die Archivseite eine ziemlich große Anzahl von Elementen enthält — 142 und zählen — und der Feed sollte nie mehr als dreißig Elemente haben.

Derzeit sieht die Ausgabe von der Archivseite etwa so aus:

<archive>
    <year>
        <month>
            <day>
            <day>
            ...
        </month>

        ...
    </year>

    ...
</archive>

Die year and und month tags are used by the HTML transform but are completely irrelevant for an Atom feed. I had hoped that using the Tags werden von der HTML-Transformation verwendet, sind aber für einen Atom-Feed völlig irrelevant. Ich hatte gehofft, dass die Verwendung der position() function with the descendant axis would work ( Funktion mit der nachfolgenden Achse funktionieren würde ( //day[position()>last()-30]), but this selects the last 30 days ), aber dies wählt die letzten 30 Tage jedes Monats aus, was überhaupt nicht das ist, was ich brauche. :-)

Gibt es eine Möglichkeit, dies mit XSLT oder XPath zu tun? Der XML-Generator zu modifizieren, um z. B. ein feed="true" attribute to the last thirty days seems like a pretty nasty kludge. Attribut zu den letzten dreißig Tagen hinzuzufügen, scheint wie ein ziemlich böses Kludge.

Antwort auf "Wie wähle ich die letzten N-Elemente mit XPath aus? " 2 von antworten

position()/last() gibt Position/letzte Position innerhalb des aktuellen Kontexts zurück, also wenn der Navigator in einem <month> positioniert ist, gibt position() <day> innerhalb dieses Monats zurück, und last() wird innerhalb dieses Monats letzt <day> zurückgegeben, aber ich denke, Sie wissen das.

Daher können Sie alle <day> in einem Array abflachen und in eine Variable setzen, bevor Sie genau wie zuvor auswählen.

<xsl:variable name="days" select="//day"/>
<xsl:apply-templates select="$days[position()>last()-30]" />

Durch die XSLT spec today, I found a note which explains why // behaves this way: behaves this way: heute stöbern, fand ich eine Notiz, die erklärt, warum // behaves this way: sich so verhält:

// is short for ist die Abkürzung für /descendant-or-self::node()/. For example, . Beispielsweise ist //para is short for kurz für /descendant-or-self::node()/child::para and so will select any und wählt daher ein beliebiges para element in the document (even a Element im Dokument aus (sogar ein para element that is a document element will be selected by -Element, das ein Dokumentelement ist, wird von //para since the document element node is a child of the root node); ausgewählt, da der Dokumentelementknoten ein untergeordnetes Element des Stammknotens ist); div//para is short for ist die Abkürzung für div/descendant-or-self::node()/child::para and so will select all und wählt daher alle para descendants of div children. Nachkommen von div-Kindern aus.

HINWEIS: Der Positionspfad //para[1] does not mean the same as the location path bedeutet nicht dasselbe wie der Positionspfad /descendant::para[1]. The latter selects the first descendant . Letzterer wählt das erste untergeordnete para element; the former selects all descendant Element aus; Erstere wählt alle nachkommenden para elements that are the first Elemente aus, die die ersten para children of their parents. Kinder ihrer Eltern sind.

Mit anderen Worten, bei Verwendung von //, the wird die position() is calculated along the entlang der child axis, not the Achse berechnet, nicht entlang der descendant-or-self axis. Specifying Achse. Wenn Sie descendant or oder descendant-or-self allows you to get the first/last angeben, können Sie die ersten/letzten n Knoten wie erwartet erhalten:

<xsl:apply-templates select="descendant::day[position()>last()-30]"/>