2010-12-15 6 views
1

Die Umwandlung, die ich schreibe, muss einen kommagetrennten Zeichenfolgenwert aus einem gegebenen Knotensatz bilden. Die resultierende Zeichenfolge muss nach einer zufälligen (nicht alphabetischen) Zuordnung für das erste Zeichen in den Eingabewerten sortiert werden.XSL-assoziative Sortierung mithilfe eines Feld-Teilstrings

kam ich mit auf den Punkt:

<?xml version="1.0" encoding="utf-8"?>  
<xsl:stylesheet  
     version="1.0"  
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
     xmlns:tmp="http://tempuri.org"  
     exclude-result-prefixes="tmp"  
>  
     <xsl:output method="xml" indent="yes"/> 

     <tmp:sorting-criterion>  
      <code value="A">5</code>  
      <code value="B">1</code>  
      <code value="C">3</code>  
     </tmp:sorting-criterion> 

     <xsl:template match="/InputValueParentNode">  
      <xsl:element name="OutputValues">  
      <xsl:for-each select="InputValue">  
        <xsl:sort select="document('')/*/tmp:sorting-criterion/code[@value=substring(.,1,1)]" data-type="number"/>  
        <xsl:value-of select="normalize-space(.)"/> 
        <xsl:if test="position() != last()">  
          <xsl:text>,</xsl:text>  
        </xsl:if> 
      </xsl:for-each>  
      </xsl:element>  
     </xsl:template>  
</xsl:stylesheet> 

Es funktioniert nicht und sieht aus wie die XPath document('')/*/tmp:sorting-criterion/code[@value=substring(.,1,1)] nicht beurteilen, wie ich erwartet. Ich habe überprüft, um die substring(.,1,1) für ein Literal zu ersetzen und es bewertet den richtigen Wert.

Also, fehlt mir etwas, das die Sortierung von XPath-Ausdruck nicht wie erwartet auswerten lässt oder ist es einfach unmöglich, es auf diese Weise zu tun?

Wenn es nicht möglich ist, einen XPath-Ausdruck zu erstellen, der funktioniert, gibt es eine Arbeit um meinen Zweck zu erreichen?

Hinweis: ich XSLT-1.0 gezwungen bin

Probe Input:

<?xml version="1.0" encoding="utf-8"?> 
<InputValueParentNode> 
     <InputValue>A input value</InputValue> 
     <InputValue>B input value</InputValue> 
     <InputValue>C input value</InputValue> 
</InputValueParentNode> 

Erwartet ouput:

<?xml version="1.0" encoding="utf-8"?> 
<OutputValues>B input value,C input value,A input value</OutputValues> 
+0

Könnten Sie beispielsweise Eingangs- und erwartete Ausgabe zur Verfügung stellen? – wdebeaum

+0

@wdebeaum: Frage bearbeitet, um beide zu enthalten. Prost. –

Antwort

2

Ersetzen Sie die self::node() Abkürzung ., mit current() Funktion.

Ein besseres Prädikat wäre: starts-with(normalize-space(current()),@value)

+0

Die Verwendung von 'current()' ist die richtige Lösung für den von Antonio geposteten Ausdruck. –

+0

@Alejandro: Vielen Dank, es funktioniert! Ich werde einen genaueren Blick auf die aktuellen/Kontext Knoten Unterschiede :) –

+0

@Antonio Perez: Sie sind willkommen. 'current()' ist eine XSLT-Funktion, die den Kontextknoten für die XSLT-Befehlsausführung zurückgibt. '.' ist die Abkürzung für' self :: node() 'in XPath 1.0, was den Context-Knoten bedeutet, aber dies würde sich mit jedem Schritt im XPath-Ausdruck ändern. –

0

Transformation gemäß Alejandro´s answer, Neben wechselnden fand ich es besser für eine XSL Variable zu verwenden ten Kartierungsdaten in Dimitre´s answer to another related question zu vermeiden, wie gesehen Deklaration eines Dummy-Namensraum (tmp).

Meine endgültige Umsetzung:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet 
     version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
     <xsl:output method="xml" indent="yes"/> 

     <xsl:template match="/InputValueParentNode"> 
      <xsl:variable name="sorting-map"> 
        <i code="A" priority="5"/> 
        <i code="B" priority="1"/> 
        <i code="C" priority="3"/> 
      </xsl:variable> 
      <xsl:variable name="sorting-criterion" select="document('')//xsl:variable[@name='sorting-map']/*"/> 

      <xsl:element name="OutputValues"> 
      <xsl:for-each select="InputValue"> 
        <xsl:sort select="$sorting-criterion[@code=substring(normalize-space(current()),1,1)]/@priority" data-type="number"/> 
        <xsl:value-of select="normalize-space(current())"/> 
        <xsl:if test="position() != last()"> 
          <xsl:text>,</xsl:text> 
        </xsl:if> 
      </xsl:for-each> 
      </xsl:element> 
     </xsl:template> 
</xsl:stylesheet> 
Verwandte Themen