Alfanumerico ordinamento misto valore di stringa
Domanda
Dato il frammento di codice XML di:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>
Ho bisogno di ordinare il MODULO nodi da form_name, in ordine alfabetico, in modo che tutti i moduli contenenti 'AI OM' in form_name sono raggruppati insieme e poi all'interno che essi sono in ordine numerico da numeri interi (lo stesso vale per altre forme).
Il form_name può essere aperto stagione come le lettere e i numeri possono essere in qualsiasi ordine:
XX ## ##
XX XX ##
XX XX ###
XX XX ## ##
XX ###
XX XXXX
'## XXX
XXX###
Ciò che io CREDO debba accadere è che la stringa deve essere suddivisa tra alfa-numerici.La parte numerica, probabilmente, potrebbe essere ordinati con spazi rimosso suppongo.
Io sono in perdita su come dividere la stringa e poi coprire tutto l'ordinamento/raggruppamento combinazioni dato che non ci sono regole circa la 'form_name' formato.
Stiamo usando XSLT 2.0.Grazie.
Soluzione
Questa trasformazione:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vDigits" select="'0123456789 '"/>
<xsl:variable name="vAlpha" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ '"/>
<xsl:template match="/*">
<forms>
<xsl:for-each select="FORM">
<xsl:sort select="translate(@form_name,$vDigits,'')"/>
<xsl:sort select="translate(@form_name,$vAlpha,'')"
data-type="number"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</forms>
</xsl:template>
</xsl:stylesheet>
quando viene applicato sul documento XML:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>
produce la volevo, risultato corretto:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="AI OM 98"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="123 DDE"/>
</forms>
Nota:
Due
<xsl:sort>
istruzioni di attuare in due fasi ordinamentoXPath
translate()
funzione viene utilizzata per produrre l'alfa-sorta-chiave o le cifre di solo ordinamento-chiave.
Altri suggerimenti
Questo foglio di stile:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="forms">
<xsl:apply-templates>
<xsl:sort select="normalize-space(
translate(@form_name,
'0123456789',
''))"/>
<xsl:sort select="substring-before(
concat(
normalize-space(
translate(@form_name,
translate(@form_name,
'0123456789 ',
''),
'')),
' '),' ')" data-type="number"/>
<xsl:sort select="substring-after(
normalize-space(
translate(@form_name,
translate(@form_name,
'0123456789 ',
''),
'')),
' ')" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Output:
<FORM lob="BO" form_name="AI OM 10"></FORM>
<FORM lob="BO" form_name="AI OM 98"></FORM>
<FORM lob="BO" form_name="AI OM 107"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 03 01"></FORM>
<FORM lob="BO" form_name="123 DDE"></FORM>
XSLT 2.0 soluzione: questo foglio di stile
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="forms">
<xsl:apply-templates>
<xsl:sort select="string-join(tokenize(@form_name,' ')
[not(. castable as xs:integer)],
' ')"/>
<xsl:sort select="xs:integer(tokenize(@form_name,' ')
[. castable as xs:integer][1])"/>
<xsl:sort select="xs:integer(tokenize(@form_name,' ')
[. castable as xs:integer][2])"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Si deve notare che la risposta segnata non funziona in tutti i casi.
Input:
<forms>
<FORM lob="BO" form_name="AA 11 AB"/>
<FORM lob="BO" form_name="AA AZ 01"/>
</forms>
Output previsto:
<forms>
<FORM lob="BO" form_name="AA AZ 01"/>
<FORM lob="BO" form_name="AA 11 AB"/>
</forms>
Output effettivo:
<forms>
<FORM lob="BO" form_name="AA 11 AB"/>
<FORM lob="BO" form_name="AA AZ 01"/>
</forms>
Se le lettere sono consentiti dopo i numeri, non è possibile spogliarli nella prima chiave di ordinamento.