2017-05-15 2 views
0

Ich versuche, Knoten in einer Variablen zu filtern/gruppieren.XSLT: Filter/Gruppenknoten in Variablen

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<row> 
    <cell n="1"/> 
    <cell n="2"/> 
    <cell n="3"/> 
    <cell n="4"/> 
    <cell n="2"/> 
    <cell n="5"/> 
</row> 

XSLT 2:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="row"> 
     <xsl:element name="row"> 
      <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="cell"> 
     <xsl:variable name="attribute" select="@n"/> 
     <xsl:variable name="sequence"> 
      <xsl:call-template name="seq"> 
       <xsl:with-param name="attribute" select="$attribute"/> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:for-each-group select="$sequence" group-by="cell/@val"> 
      <xsl:sequence select="."></xsl:sequence> 
     </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template name="seq"> 
     <xsl:param name="attribute"/> 
     <xsl:element name="cell"> 
      <xsl:attribute name="val"> 
       <xsl:value-of select="$attribute"/> 
      </xsl:attribute> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

Vorgesehen Ausgabe:

<?xml version="1.0" encoding="UTF-8"?> 
<row> 
    <cell val="1"/> 
    <cell val="2"/> 
    <cell val="3"/> 
    <cell val="4"/> 
    <cell val="5"/> 
</row> 

Der XML-Kodex ist nur ein Beispiel für eine viel kompliziertere Datei. Ich möchte zuerst alle Elemente cell bearbeiten und das Ergebnis in einer Variablen speichern. Im zweiten Lauf möchte ich die Knoten der Sequenz filtern oder neu gruppieren.

Ich habe auch versucht $sequence mit Prädikaten zu filtern:

<xsl:sequence select="$sequence/*[@val != preceding-sibling::cell/@val]"/> 

die Ausgabedatei leer In diesem Fall ist.

EDIT 2 (jetzt es funktioniert):

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:template match="row"> 
    <xsl:variable name="sequence"> 
     <xsl:for-each select="cell"> 
      <xsl:variable name="attribute" select="@n"/> 
      <xsl:call-template name="seq"> 
       <xsl:with-param name="attribute" select="$attribute"/> 
      </xsl:call-template> 
     </xsl:for-each> 
    </xsl:variable> 
    <row> 
     <xsl:for-each-group group-by="@val" select="$sequence/*"> 
      <xsl:sequence select="."/> 
     </xsl:for-each-group> 
    </row> 
</xsl:template> 

<xsl:template name="seq"> 
    <xsl:param name="attribute"/> 
    <xsl:element name="cell"> 
     <xsl:attribute name="val"> 
      <xsl:value-of select="$attribute"/> 
     </xsl:attribute> 
    </xsl:element> 
</xsl:template> 

+1

Ihr Beispiel ist überhaupt nicht klar. Wenn Sie zuerst alle 'cell'-Elemente verarbeiten und das Ergebnis zur weiteren Verarbeitung in einer Variablen speichern wollen, müssen Sie dies aus dem Kontext von 'row' (oder höher) tun. Ich denke, das ist alles, was man an dieser Stelle sagen kann. –

+0

Ich habe versucht, den früheren Code zu bearbeiten, aber jetzt kann ich das $ -Attribut nicht mehr übergeben. Ich fürchte, dass meine XSLT-Kenntnisse hier ihre Grenzen finden. – Ferestes

+0

Ditto Michaels Kommentar - es ist nicht klar, was Sie zu tun versuchen. Ich würde auch hinzufügen, dass Ihre '$ sequenz' -Variable immer nur ein einzelnes' cell'-Element enthält, effektiv eine Kopie des 'cell' -Elements, das der Kontext für die Übereinstimmung in' '. Da '$ sequence' nur ein einzelnes Element hat, scheitert Ihr Versuch,' $ sequence' mit 'previous-sibling' zu filtern. Um mehr als eine "Zelle" gleichzeitig anzusprechen, müssen Sie, wie Michael sagt, mit dem Kontext von "Zeile" oder höher beginnen. –

Antwort

1

Hier ist ein XSLT 2.0 Sheet, das <cell n="x">...</cell> in <cell val="n">...</cell> zuerst und dann Gruppen sind solche Zellenelemente durch die Transformationen val Attribut zum Entfernen von Dubletten:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="row"> 
     <xsl:copy> 
      <xsl:variable name="transformed-cells"> 
       <xsl:apply-templates select="cell"/> 
      </xsl:variable> 
      <xsl:for-each-group select="$transformed-cells/cell" group-by="@val"> 
       <xsl:copy-of select="."/> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="cell/@n"> 
     <xsl:attribute name="val" select="."/> 
    </xsl:template> 

</xsl:transform> 

Ausgang ist

<row> 
    <cell val="1"/> 
    <cell val="2"/> 
    <cell val="3"/> 
    <cell val="4"/> 
    <cell val="5"/> 
</row> 

http://xsltransform.net/a9Giwz

+0

Vielen Dank! Ich fürchte, mein Beispiel war nicht so gut.Es geht nicht um die beabsichtigte Ausgabe, sondern darum, die Ausgabe zu erreichen, indem man eine Variable verwendet, die das Ergebnis einer aufgerufenen Vorlage speichert. – Ferestes

+1

Nun, ob innerhalb der 'xsl: variable'' xsl: call-template' (wie Sie scheinen aus Gründen zu tun, die ich nicht verstehe) oder 'xsl: apply-templates' (wie ich es im Beispiel getan habe, wie es in XSLT üblich ist, um Knoten zu verarbeiten), ändert nichts an der Verwendung der Variablen in der 'xsl: for-each-group' in meiner Antwort. Diese Antwort sollte helfen, den Inhalt der Variablen zu verarbeiten. –

+0

Ich möchte 'xsl: call-template', weil das Stylesheet, auf das ich mich beziehe, es benutzt. Wie auch immer, du hast Recht. Ich habe 'xsl: for-each-group' falsch verwendet. Jetzt geht es ganz gut. Vielen Dank. – Ferestes