Procedimiento para personalizar la representación de un campo en una vista de lista

Última modificación: martes, 29 de marzo de 2011

Hace referencia a: SharePoint Foundation 2010

En este artículo
Introducción a la representación de campos personalizados en vistas de lista
Definición de representación personalizada para un campo personalizado
Ejemplo: Personalización del campo Moneda

En este tema se explica cómo se puede definir la forma en que se representará el campo personalizado en las vistas de lista.

Introducción a la representación de campos personalizados en vistas de lista

Microsoft SharePoint Foundation usa hojas de estilos XSLT para representar las vistas de lista. (Para obtener una descripción del sistema, vea Información general del sistema de representación de vistas de listas XSLT). Una lista se representa como una tabla HTML y el valor de un campo se representa en la celda apropiada de la tabla mediante una simple plantilla XSLT del archivo fldtypes.xsl ubicado en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL. Hay muchas plantillas en ese archivo para representar valores de campo. La plantilla que se use dependerá de varios factores, de los cuales el más importante es el tipo del campo definido por la enumeración SPFieldType. Por ejemplo, hay una plantilla FieldRef_Number_body para campos Number y una plantilla FieldRef_Text_body para campos Text.

Nota

No hay una correspondencia uno a uno entre los tipos de campos y las plantillas. Por ejemplo, hay varias plantillas distintas para los campos calculados y la plantilla FieldRef_Number_body se usa tanto para camposCurrrency() como campos Number.

Por ejemplo, a continuación se muestra la plantilla FieldRef_Text_body.

<xsl:template name="FieldRef_Text_body" ddwrt:dvt_mode="body" match ="FieldRef" mode="Text_body">
  <xsl:param name="thisNode" select="."/>
  <xsl:choose>
    <xsl:when test="@AutoHyperLink='TRUE'">
      <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" disable-output-escaping ="yes"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

El parámetro thisNode que se pasa a esta plantilla se compone de marcado dsQueryResponse que contiene los elementos de la lista (hasta el máximo permitido por página). Para obtener un ejemplo de este marcado, vea Ejemplos de árboles de nodos de resultados y de entrada en transformaciones XSLT.

Tenga en cuenta también que la plantilla se bifurca en función de si el campo se ha definido automáticamente para aplicar formato a cadenas que se asemejan a direcciones URL como vínculos <a> de HTML. Si es así, cuando el procesador XSLT representa el HTML para el campo, no reemplaza caracteres importantes, como "<" y "&", con sus entidades de caracteres equivalentes (&lt; y &amp;), como haría normalmente un procesador XSLT compatible de manera predeterminada. Aparte de esta complejidad, la plantilla envía el valor del campo con la siguiente línea.

<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>

Dado que esta línea aparece prácticamente en todas las plantillas XSLT de la representación del campo, merece una descripción más detallada. El primer paso de la expresión XPath que identifica el nodo cuyo valor se va a representar es simplemente una referencia al parámetro thisNode, por lo que el resto de los pasos se interpreta con respecto a la raíz del marcado en dicho parámetro. El siguiente paso antes de que se apliquen los predicados es /@*. Esto hace referencia a todos los atributos de la raíz y sus descendientes; por lo tanto, en este caso, se refiere a todos los atributos de todos los elementos de thisNode. El [name()=current()/@Name] predicado restringe aún más la selección. A la izquierda del "=" está la función XSLT name(). Representa el nombre de un nodo en la secuencia producida por el elemento "$thisNode/@*". En otras palabras, representa el nombre de un atributo en algún elemento de thisNode. Si se aplica esto al ejemplo thisNode de Ejemplos de árboles de nodos de resultados y de entrada en transformaciones XSLT, se puede ver que algunos de los atributos que contiene tienen un nombre basado en los nombres internos de campos del elemento de lista; por ejemplo, Attachments, Title y el campo personalizado ISBN. El lado derecho del "=" es una referencia al atributo Name del nodo actual en el árbol de nodo de origen: current()/@Name. Dado que esta plantilla se declara con match ="FieldRef", se aplica solo a elementos FieldRef; por lo tanto, la función current() se refiere a un elemento FieldlRef. Por lo tanto, todo el elemento xsl:value-of dice "emitir el valor del atributo de thisNode cuyo nombre es igual al nombre del FieldRef actual en el árbol de nodo de origen".

Por lo tanto, cuando se está procesando el FieldRefTitle del árbol de nodo de origen de ejemplo, el procesador XSLT emite para este el valor del atributo Title del elemento Row actual del marcado thisNode. (Esto sería "Theories of Truth", para la primera fila). Del mismo modo, se representa el valor del atributo ISBN de esa misma Row cuando se procesa el ISBN FieldRef del árbol de nodo de origen ("0-262-61107-4").

En la mayoría de los casos, el campo personalizado obtendrá una representación predeterminada, que está determinada principalmente por su tipo base y es exactamente la que desea. En el caso de un campo de texto, por ejemplo, el valor se representa como texto sin formato en la celda correspondiente de la tabla HTML. Si desea que el campo personalizado se represente de alguna forma especial, debe usar una hoja de estilos XSLT para definir cómo se representará. La sección siguiente muestra cómo hacerlo.

Definición de representación personalizada para un campo personalizado

El siguiente procedimiento muestra cómo crear una hoja de estilos XSLT personalizada para representar un tipo de campo personalizado.

Para crear una hoja de estilos XSLT personalizada para la representación de un campo

  1. Cree un archivo de texto con la extensión "xsl". Debe asignársele un nombre según el modelo fldtypes_*.xsl, donde "*" representa cualquier cadena de caracteres de nombre de archivo permitidos. Considere la posibilidad de usar el nombre del campo personalizado, como fldtypes_ISBN.xsl. Si va a tener varias hojas de estilo XSLT personalizadas, considere la posibilidad de usar el nombre de la compañía, por ejemplo fldtypes_Contoso.xsl, y de incluirlas todas en el mismo archivo. Evite el uso de una cadena que otro proveedor de soluciones podría usar.

  2. Agregue la siguiente declaración de la hoja de estilos en el archivo.

    <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                    xmlns:d="https://schemas.microsoft.com/sharepoint/dsp"
                    version="1.0"
                    exclude-result-prefixes="xsl msxsl ddwrt"
                    xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime"
                    xmlns:asp="https://schemas.microsoft.com/ASPNET/20"
                    xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" 
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                    xmlns:SharePoint="Microsoft.SharePoint.WebControls"
                    xmlns:ddwrt2="urn:frontpage:internal">
    
    
    </xsl:stylesheet>
    
  3. Abra el archivo denominado fldtypes.xsl en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL y busque la plantilla que representa el campo de manera predeterminada. Si, por ejemplo, el tipo base del campo es Moneda, la plantilla es FieldRef_Number_body. Copie la plantilla como elemento secundario del elemento xsl:stylesheet. El siguiente ejemplo muestra el uso de la plantilla FieldRef_Number_body.

    <xsl:stylesheet > <!-- stylesheet attributes omitted for brevity -->
    
      <xsl:template name="FieldRef_Number_body" ddwrt:dvt_mode="body" match="FieldRef" mode="Number_body">
        <xsl:param name="thisNode" select="."/>
        <xsl:choose>
          <xsl:when test="$FreeForm">
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <div align="right">
              <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
                <xsl:with-param name="thisNode" select="$thisNode"/>
              </xsl:call-template>
            </div>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
    </xsl:stylesheet>
    
  4. Elimine el atributo name del elemento xsl:template (en este caso, name="FieldRef_Number_body"). Elimine también el atributo ddwrt:dvt_mode, si está presente.

  5. Cambie el atributo match de forma tal que la plantilla coincida solo con campos que tienen exactamente el mismo nombre interno que el campo personalizado. Para ello se requiere un predicado XSLT que especifique el valor requerido del atributo Name del elemento FieldRef. Por ejemplo, suponga que tiene un campo Pérdidas y ganancias netas cuyo nombre interno es "Net_x0020_Profit_x002f_Loss". La etiqueta inicial de la plantilla debería verse como se muestra a continuación.

    <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    

    Esto garantiza que se está personalizando la representación únicamente del tipo de campo personalizado, y no de todos los campos que tengan Moneda o Número como tipo base.

  6. Edite y agregue al marcado de la plantilla para crear el efecto de representación que desee. Para obtener un ejemplo, vea la sección siguiente.

  7. Guarde y copie el archivo fldtypes_*.xsl a %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL en todos los servidores.

  8. Restablezca la aplicación web para que se vuelvan a cargar los archivos en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL. El archivo personalizado invalida cualquiera de los archivos integrados.

Ejemplo: Personalización del campo Moneda

Como ejemplo detallado del paso 6, en esta sección se muestra cómo representar el valor del campo Pérdidas y ganancias netas en rojo cuando es un número negativo. Después del paso 5, la plantilla debería ser como se muestra a continuación.

<xsl:stylesheet > <!-- stylesheet attributes omitted for brevity -->

  <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>
    <xsl:choose>
      <xsl:when test="$FreeForm">
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <div align="right">
          <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
            <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
        </div>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

Primero tenga en cuenta que la representación predeterminada se bifurca en función de la prueba del parámetro FreeForm. Esta prueba devuelve true si el atributo Type del elemento Toolbar en el árbol de nodo de origen es "FreeForm". Si el valor del atributo es "Standard", o si el atributo simplemente no está presente, la plantilla agrega marcado HTML para justificar a la derecha el valor del campo dentro de la celda. (Vea en Ejemplos de árboles de nodos de resultados y de entrada en transformaciones XSLT un ejemplo de un árbol de nodo de origen y su elemento Toolbar. Vea también Elemento Toolbar (Vista) para obtener más información). Dado que los valores negativos deberían estar en rojo independientemente del tipo de barra de herramientas, debe realizar los cambios en el marcado en ambas ramas.

Tenga en cuenta además que la plantilla llama a otra plantilla, denominada FieldRef_ValueOf_DisableEscape, para representar el valor. Esta última plantilla también está en fldtypes.xsl y se define como se indica a continuación.

<xsl:template name="FieldRef_ValueOf_DisableEscape" ddwrt:dvt_mode="body">
  <xsl:param name="thisNode" select="."/>
  <xsl:value-of disable-output-escaping="yes" select="$thisNode/@*[name()=current()/@Name]" />
</xsl:template>

Como se muestra en el ejemplo, la única diferencia de esta plantilla con respecto a la plantilla de representación de campo estándar que usa la línea <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" /> para representar el valor del campo es que agrega el atributo disable-output-escaping="yes", que se explicó anteriormente en este tema.

En el elemento <xsl:when test="$FreeForm">, agregue una estructura choose-when-otherwise y mueva la llamada existente a la plantilla FieldRef_ValueOf_DisableEscape en el elemento <xsl:otherwise>, tal como se muestra en el siguiente ejemplo.

<xsl:when test="$FreeForm">
  <xsl:choose> 
    <when test=""> 

    </when> 
    <otherwise>
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
    </otherwise> 
  </choose>
</xsl:when>

El valor test debería ser true cada vez que el valor del campo Net_x0020_Profit_x002f_Loss actual sea negativo; es decir, cada vez que el valor sea inferior a cero. Ya vimos que $thisNode/@*[name()=current()/@Name] se evalúa con respecto al campo actual. No obstante, los campos de moneda en SharePoint Foundation obtienen un formato de bajo nivel incluso antes de aplicar cualquier formato XSLT. Específicamente, un valor de moneda negativo se expresa entre paréntesis en vez de usar un signo menos. Por ejemplo, una pérdida de 497.882,87 $ se expresa como ($497.882,87) en vez de -$497.882,87. Esto crea un problema, ya que el procesador XSLT trata cualquier expresión parentética como mayor que 0, por lo que no se puede comparar directamente el valor de $thisNode/@*[name()=current()/@Name] con cero. Afortunadamente, para los tipos de campo Moneda, SharePoint Foundation agrega al marcado del parámetro thisNode una segunda versión del valor del campo como un simple valor de tipo doble que, cuando es negativo, se expresa con un signo menos. Específicamente, esta versión es el valor de un atributo del elemento Row que tiene el mismo nombre que el atributo Net_x0020_Profit_x002f_Loss, salvo que se anexa un solo "." al final del nombre del atributo. Por ejemplo, compare los atributos "Retail_x0020_Price" y "Retail_x0020_Price." del elemento Row en el ejemplo de "thisNode" en Ejemplos de árboles de nodos de resultados y de entrada en transformaciones XSLT.

Use este atributo con el nombre que termina en un punto para comprobar si el valor es negativo. La expresión de test debería ser como se muestra a continuación.

<xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0">
SugerenciaSugerencia

Se debe usar "&lt;" en lugar de "<", ya que el procesador XSLT interpretaría este último como el comienzo de un elemento. Si lo prefiere, puede invertir los operandos, lo que le permite usar un simple signo ">": "0 > $thisNode/@*[name()=concat(current()/@Name, '.')]".

Ahora, dentro de la estructura when interna, copie la llamada a la plantilla FieldRef_ValueOf_DisableEscape pero, inclúyala en literales HTML que coloreen el valor de rojo. A continuación se muestra el aspecto que debería tener la estructura when exterior.

<xsl:when test="$FreeForm">
  <xsl:choose> 
    <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
      <span style="color:red">
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
      </span>
    </xsl:when> 
    <xsl:otherwise>
      <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
        <xsl:with-param name="thisNode" select="$thisNode"/>
      </xsl:call-template>
    </xsl:otherwise> 
  </xsl:choose>
</xsl:when>

Como se indicó anteriormente, el campo debería representar el mismo color independientemente del tipo de barra de herramientas, por lo que toda la estructura choose interior debería convertirse en el contenido del elemento div dentro de la parte otherwise de la estructura choose exterior. De este modo, se produce la definición de plantilla indicada a continuación.

<xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>

  <xsl:choose>
    <xsl:when test="$FreeForm">
      <xsl:choose> 
        <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
          <span style="color:red">
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
          </span>
        </xsl:when> 
        <xsl:otherwise>
          <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
            <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
        </xsl:otherwise> 
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>    
      <div align="right">
        <xsl:choose> 
          <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
            <span style="color:red">
              <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
                <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
            </span>
          </xsl:when> 
          <xsl:otherwise>
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
          </xsl:otherwise> 
        </xsl:choose>
      </div>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template

Esto puede hacerse más fácil de mantener si las partes repetitivas se encapsulan mediante parámetros y variables XSLT, y mediante la anidación de las plantillas. La siguiente es una versión de la hoja de estilos en la que se usan estas técnicas.

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                xmlns:d="https://schemas.microsoft.com/sharepoint/dsp"
                version="1.0"
                exclude-result-prefixes="xsl msxsl ddwrt"
                xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime"
                xmlns:asp="https://schemas.microsoft.com/ASPNET/20"
                xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:SharePoint="Microsoft.SharePoint.WebControls"
                xmlns:ddwrt2="urn:frontpage:internal">

  <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>
    
    <xsl:variable name="FieldValue">   
      <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
        <xsl:with-param name="thisNode" select="$thisNode" />
      </xsl:call-template>
    </xsl:variable>
           
    <xsl:variable name="ValueIsNegative">
      <xsl:value-of select="$thisNode/@*[name()=concat(current()/@Name, '.')]  &lt; 0" />
    </xsl:variable>
    
    <xsl:choose>
      <xsl:when test="$FreeForm">
        <xsl:call-template name="RedWhenNegative_ElseBlack" >  
             <xsl:with-param name="thisNode" select="$thisNode" />
             <xsl:with-param name="ValueIsNegative" select="$ValueIsNegative" />
               <xsl:with-param name="FieldValue" select="$FieldValue" />
          </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>    
        <div align="right">
          <xsl:call-template name="RedWhenNegative_ElseBlack" >  
        <xsl:with-param name="thisNode" select="$thisNode" />
        <xsl:with-param name="ValueIsNegative" select="$ValueIsNegative" />
        <xsl:with-param name="FieldValue" select="$FieldValue" />
              </xsl:call-template>
        </div>
      </xsl:otherwise>
    </xsl:choose>
    
  </xsl:template>
  
  <xsl:template name="FieldValueInRed">
    <xsl:param name="thisNode" select="." />
    <xsl:param name="FieldValue" select="." />
    
    <span style="color:red">
      <xsl:value-of select="$FieldValue" />
    </span>
    
  </xsl:template>
  
  <xsl:template name="RedWhenNegative_ElseBlack">
    <xsl:param name="thisNode" select="." />
    <xsl:param name="ValueIsNegative" select="." />
    <xsl:param name="FieldValue" select="." />
    
    <xsl:choose> 
      <xsl:when test="$ValueIsNegative='true'">
          <xsl:call-template name="FieldValueInRed">
            <xsl:with-param name="thisNode" select="$thisNode" />
                <xsl:with-param name="FieldValue" select="$FieldValue" />
          </xsl:call-template>      
      </xsl:when> 
      <xsl:otherwise>
        <xsl:value-of select="$FieldValue" />
      </xsl:otherwise> 
    </xsl:choose>

  </xsl:template>
  
</xsl:stylesheet>

La figura 1 muestra la forma en que el campo aparece en una lista.

Figura 1: Un campo de moneda con los valores negativos en rojo

Columna de moneda con un valor negativo en rojo

Vea también

Tareas

Tutorial: Crear un tipo de campo personalizado

Conceptos

Tipos de campos personalizados