xml - tablas - ¿Cómo puedo dividir una fila de la tabla en xsl después de un conteo especificado?
pasos para insertar una tabla en dreamweaver (4)
Tengo el siguiente xsl que ordena mi xml alfabéticamente:
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:key name="rows-by-title" match="Row" use="translate(substring(@Title,1,1),''abcdefghijklmnopqrstuvwxyz'',''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
<xsl:variable name="StartRow" select="string(''<tr >'')" />
<xsl:template name="Meunchian" match="/dsQueryResponse/Rows">
<table>
<tr>
<xsl:for-each select="Row[count(. | key(''rows-by-title'', translate(substring(@Title,1,1),''abcdefghijklmnopqrstuvwxyz'',''ABCDEFGHIJKLMNOPQRSTUVWXYZ''))[1]) = 1]">
<xsl:sort select="translate(substring(@Title,1,1),''abcdefghijklmnopqrstuvwxyz'',''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
<!-- Puts out the title -->
<td>
<xsl:value-of select="translate(substring(@Title,1,1),''abcdefghijklmnopqrstuvwxyz'',''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
</td>
<!-- Now all it''s children -->
<xsl:for-each select="key(''rows-by-title'', translate(substring(@Title,1,1),''abcdefghijklmnopqrstuvwxyz'',''ABCDEFGHIJKLMNOPQRSTUVWXYZ''))">
<xsl:value-of select="@Title" /><br/>
</xsl:for-each>
</xsl:for-each>
</tr>
</table>
</xsl:template>
XML:
<dsQueryResponse>
<Rows>
<Row Title="Agenda" />
<Row Title="Policy" />
<Row Title="Policy" />
<Row Title="Report" />
<Row Title="Report" />
</Rows>
</dsQueryResponse>
Ahora quiero dividir la fila de la tabla cada 4 columnas que salen para que la salida se vea algo así como:
ABCD
EFGH
IJKL
MNOP
QRST
UVWX
YZ
¿Alguien puede sugerir la mejor manera de lograr esto?
Muchas gracias
La pregunta me confunde un poco, pero creo que lo que estás buscando es una prueba xsl: if con una combinación de posición () y mod
Aquí está mi solución.
Puede decidir a través de los parámetros "per-row"
y "show-empty"
si desea que aparezcan celdas vacías o si desea ocultarlas. Estoy seguro de que existe una versión mucho más elegante, pero no pude encontrar una. ;-) Comentarios bienvenidos.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0" encoding="iso-8859-1" indent="yes"/>
<xsl:key name="rows-by-title" match="Row" use="translate(substring(@Title, 1, 1), ''abcdefghijklmnopqrstuvwxyz'', ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
<xsl:variable name="alphabet" select="string(''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
<xsl:variable name="per-row" select="number(4)" />
<xsl:variable name="show-empty" select="false()" />
<xsl:template match="/">
<xsl:apply-templates select="dsQueryResponse/Rows" />
</xsl:template>
<xsl:template match="Rows">
<table>
<xsl:call-template name="create-rows" />
</table>
</xsl:template>
<xsl:template name="create-rows">
<xsl:param name="index" select="1" />
<xsl:variable name="letters">
<xsl:call-template name="next-letters">
<xsl:with-param name="index" select="$index" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="$letters != ''''">
<tr title="{$letters}">
<xsl:call-template name="create-cells">
<xsl:with-param name="letters" select="$letters" />
</xsl:call-template>
</tr>
</xsl:if>
<xsl:if test="string-length($letters) = $per-row">
<xsl:call-template name="create-rows">
<xsl:with-param name="index" select="string-length(substring-before($alphabet, substring($letters, string-length($letters), 1))) + 2" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="next-letters">
<xsl:param name="index" />
<xsl:variable name="letter" select="substring($alphabet, $index, 1)" />
<xsl:variable name="letters">
<xsl:if test="$index <= string-length($alphabet)">
<xsl:if test="$show-empty or key(''rows-by-title'', $letter)">
<xsl:value-of select="$letter" />
</xsl:if>
<xsl:call-template name="next-letters">
<xsl:with-param name="index" select="$index + 1" />
</xsl:call-template>
</xsl:if>
</xsl:variable>
<xsl:value-of select="substring($letters, 1, $per-row)" />
</xsl:template>
<xsl:template name="create-cells">
<xsl:param name="letters" />
<xsl:variable name="letter" select="substring($letters, 1, 1)" />
<xsl:if test="$letter != ''''">
<td title="{$letter}">
<strong>
<xsl:value-of select="$letter" />
</strong>
<xsl:apply-templates select="key(''rows-by-title'', $letter)">
<xsl:sort select="@Title" />
</xsl:apply-templates>
</td>
<xsl:call-template name="create-cells">
<xsl:with-param name="letters" select="substring($letters, 2, string-length($letters) - 1)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="Row">
<br />
<xsl:value-of select="@Title" />
</xsl:template>
</xsl:stylesheet>
Con esta entrada:
<dsQueryResponse>
<Rows>
<Row Title="Agenda" />
<Row Title="Policy" />
<Row Title="Policy" />
<Row Title="Report" />
<Row Title="Report" />
<Row Title="Test2" />
<Row Title="Test1" />
<Row Title="Boo" />
<Row Title="Foo" />
</Rows>
</dsQueryResponse>
Este resultado se produce (los atributos del title
fueron solo para la depuración. Los dejé, elimínelos en cualquier momento):
<table>
<tr title="ABFP">
<td title="A">
<strong>A</strong>
<br>Agenda
</td>
<td title="B">
<strong>B</strong>
<br>Boo
</td>
<td title="F">
<strong>F</strong>
<br>Foo
</td>
<td title="P">
<strong>P</strong>
<br>Policy
<br>Policy
</td>
</tr>
<tr title="RT">
<td title="R">
<strong>R</strong>
<br>Report
<br>Report
</td>
<td title="T">
<strong>T</strong>
<br>Test1
<br>Test2
</td>
</tr>
</table>
Esta pregunta debe ser editada para que cualquiera pueda entender cuál es realmente el problema . El comentario de Tomalak revela que el OP " quiere listas de elementos en una cuadrícula ordenada alfabéticamente. Una lista para cada letra. Cuatro letras en sentido horizontal, tanto como verticalmente "
La siguiente transformación :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
extension-element-prefixes="ext"
>
<xsl:variable name="vDoc" select="/"/>
<xsl:variable name="vNumCols" select="4"/>
<xsl:variable name="vLower"
select="''abcdefghijklmnopqrstuvwxyz''"
/>
<xsl:variable name="vUpper"
select="''ABCDEFGHIJKLMNOPQRSTUVWXYZ''"
/>
<xsl:key name="rows-by-FirstLetter" match="Row"
use="translate(substring(@Title,1,1),
''abcdefghijklmnopqrstuvwxyz'',
''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" />
<xsl:variable name="vrtfStartLetters">
<xsl:for-each select=
"/*/*/Row
[count(.
|
key(''rows-by-FirstLetter'',
translate(substring(@Title,1,1),
$vLower,
$vUpper)
)[1]
)
= 1
]">
<startLetter>
<xsl:value-of select=
"translate(substring(@Title,1,1),
$vLower,
$vUpper)"/>
</startLetter>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vStartLetters" select=
"ext:node-set($vrtfStartLetters)"/>
<xsl:template match="Rows">
<table>
<xsl:apply-templates select=
"$vStartLetters/*[position() mod $vNumCols = 1]">
<xsl:with-param name="pDoc" select="$vDoc"/>
<xsl:with-param name="pNumCols" select="$vNumCols"/>
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="startLetter">
<xsl:param name="pDoc"/>
<xsl:param name="pNumCols" select="10"/>
<tr>
<xsl:apply-templates mode="copy" select=
". | following-sibling::*
[not(position() >= $pNumCols)]">
<xsl:with-param name="pDoc" select="$pDoc"/>
<xsl:sort/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="startLetter" mode="copy">
<xsl:param name="pDoc"/>
<xsl:variable name="pThis" select="."/>
<td>
<xsl:value-of select="."/>
<br />
<table>
<xsl:for-each select="$pDoc">
<xsl:for-each select="key(''rows-by-FirstLetter'', $pThis)">
<tr><td><xsl:value-of select="@Title"/></td></tr>
</xsl:for-each>
</xsl:for-each>
</table>
</td>
</xsl:template>
</xsl:stylesheet>
cuando se aplica en este documento XML :
<dsQueryResponse>
<Rows>
<Row Title="Agenda" />
<Row Title="Accrual" />
<Row Title="Ads" />
<Row Title="Averages" />
<Row Title="Bindings" />
<Row Title="Budget" />
<Row Title="Cars" />
<Row Title="Categories" />
<Row Title="Costs" />
<Row Title="Policy" />
<Row Title="Politics" />
<Row Title="Reevaluations" />
<Row Title="Report" />
</Rows>
</dsQueryResponse>
produce el resultado deseado :
<table>
<tr>
<td>A
<br/>
<table>
<tr>
<td>Agenda</td>
</tr>
<tr>
<td>Accrual</td>
</tr>
<tr>
<td>Ads</td>
</tr>
<tr>
<td>Averages</td>
</tr>
</table>
</td>
<td>B
<br/>
<table>
<tr>
<td>Bindings</td>
</tr>
<tr>
<td>Budget</td>
</tr>
</table>
</td>
<td>C
<br/>
<table>
<tr>
<td>Cars</td>
</tr>
<tr>
<td>Categories</td>
</tr>
<tr>
<td>Costs</td>
</tr>
</table>
</td>
<td>P
<br/>
<table>
<tr>
<td>Policy</td>
</tr>
<tr>
<td>Politics</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>R
<br/>
<table>
<tr>
<td>Reevaluations</td>
</tr>
<tr>
<td>Report</td>
</tr>
</table>
</td>
</tr>
</table>
Tenga en cuenta tres cosas :
Estamos utilizando la función de extensión ( exslt ) ext: node-set () para convertir un resultado intermedio de RTF (Result-Tree Fragment) en un árbol temporal.
<xsl:for-each select="$pDoc">
necesario para volver a convertir el documento XML original en el documento XML actual, de modo que la función key () utilice el índice creado para este documento y no para el árbol temporal.Cada letra de inicio que debe comenzar una nueva fila de (4) letras iniciales se procesa en una plantilla especial, en la que se genera
<tr>
. Entonces, esta y las restantes (3) letras iniciales de la fila se procesan dentro del cuerpo del modo<tr>
en "copia", simplemente creando una<td>
cada una.
Aquí hemos cubierto y demostrado algunas técnicas avanzadas de XSLT :
- Usar el operador de
mod
para agrupar por cantidad. - Usar la función de tecla () para un documento diferente al actual.
- Modos
- Convirtiendo un RTF en un árbol temporal
Disfruta :)
Aquí hay una segunda solución, que no requiere ninguna función de extensión . Tenga en cuenta que no es recursivo y puede ser más eficiente que uno recursivo.
Esta transformación :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:namespace" exclude-result-prefixes="my" > <xsl:output method="html"/> <my:alpha> <l>A</l><l>B</l><l>C</l><l>D</l><l>E</l> <l>F</l><l>G</l><l>H</l><l>I</l><l>J</l> <l>K</l><l>L</l><l>M</l><l>N</l><l>O</l> <l>P</l><l>Q</l><l>R</l><l>S</l><l>T</l> <l>U</l><l>V</l><l>W</l><l>X</l><l>Y</l> <l>Z</l> </my:alpha> <xsl:variable name="vDoc" select="/"/> <xsl:variable name="vNumCols" select="4"/> <xsl:variable name="vLower" select="''abcdefghijklmnopqrstuvwxyz''" /> <xsl:variable name="vUpper" select="''ABCDEFGHIJKLMNOPQRSTUVWXYZ''" /> <xsl:key name="rows-by-FirstLetter" match="Row" use="translate(substring(@Title,1,1), ''abcdefghijklmnopqrstuvwxyz'', ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'')" /> <xsl:variable name="vStartingLetters"> <xsl:for-each select= "/*/*/Row [generate-id() = generate-id(key(''rows-by-FirstLetter'', translate(substring(@Title,1,1), $vLower, $vUpper) )[1] ) ]"> <xsl:value-of select= "translate(substring(@Title,1,1), $vLower, $vUpper)"/> </xsl:for-each> </xsl:variable> <xsl:variable name="vMyLetters" select= "document('''')/*/my:alpha/l[contains($vStartingLetters,.)]" /> <xsl:template match="Rows"> <table> <xsl:for-each select= "$vMyLetters[position() mod $vNumCols = 1]"> <xsl:variable name="vPos" select="(position()-1)*$vNumCols+1"/> <tr> <xsl:apply-templates select= "$vMyLetters[position() >= $vPos and not(position() > $vPos+$vNumCols -1) ]"> <xsl:with-param name="pDoc" select="$vDoc"/> </xsl:apply-templates> </tr> </xsl:for-each> </table> </xsl:template> <xsl:template match="l"> <xsl:param name="pDoc"/> <xsl:variable name="pThis" select="."/> <td> <xsl:value-of select="."/> <br /> <table> <xsl:for-each select="$pDoc"> <xsl:for-each select= "key(''rows-by-FirstLetter'', $pThis)"> <tr> <td> <xsl:value-of select="@Title"/> </td> </tr> </xsl:for-each> </xsl:for-each> </table> </td> </xsl:template> </xsl:stylesheet>
cuando se aplica en el siguiente documento XML:
<dsQueryResponse> <Rows> <Row Title="Agenda" /> <Row Title="Policy" /> <Row Title="Policy" /> <Row Title="Report" /> <Row Title="Report" /> <Row Title="Test2" /> <Row Title="Test1" /> <Row Title="Boo" /> <Row Title="Foo" /> </Rows> </dsQueryResponse>
produce el resultado deseado:
<table> <tr> <td>A<br><table> <tr> <td>Agenda</td> </tr> </table> </td> <td>B<br><table> <tr> <td>Boo</td> </tr> </table> </td> <td>F<br><table> <tr> <td>Foo</td> </tr> </table> </td> <td>P<br><table> <tr> <td>Policy</td> </tr> <tr> <td>Policy</td> </tr> </table> </td> </tr> <tr> <td>R<br><table> <tr> <td>Report</td> </tr> <tr> <td>Report</td> </tr> </table> </td> <td>T<br><table> <tr> <td>Test2</td> </tr> <tr> <td>Test1</td> </tr> </table> </td> </tr> </table>
Tenga en cuenta que la mayoría de las explicaciones en mi primera respuesta se aplican también a esta solución con la única excepción de que aquí no usamos modos.