WSS 3.0 & MOSS: Disponible el SP3!

Tal y como podéis leer en este enlace, Microsoft acaba de liberar el service pack 3 (SP3) para la versión 2007 de SharePoint (WSS 3.0 & MOSS). En ese mismo post se comenta que junto con el SP3 de SharePoint, también tenemos disponible el SP3 de Office 2007. Los enlaces de descarga respectivos son los siguientes:

2007 Microsoft Office Suite Service Pack 3 (SP3) and Microsoft Office Language Pack 2007 SP3

2526086

Suite: 32-bit ; LPK: 32-bit

2007 Microsoft Office servers Service Pack 3 (SP3) and 2007 Microsoft Office servers Language Pack (SP3)

2526299

Server Suite: 32-bit; LPK: 32-bit ; Server Suite: 64-bit; LPK: 64-bit

Office SharePoint Designer 2007 Service Pack 3 (SP3) and of Office SharePoint Designer Language Pack 2007 SP3

2526089

SharePoint Designer: 32-bit; LPK: 32bit

Office Project 2007 Service Pack 3 (SP3) and of Office Project Language Pack 2007 SP3

2526091

Project: 32-bit; Project LPK: 32-bit

Office Visio 2007 Service Pack 3 (SP3) and of Office Visio Language Pack 2007 SP3

2526291

Visio: 32-bit; Visio LPK: 32-bit

Office Proofing Tools 2007 Service Pack 3 (SP3)

2526293

32-bit

Microsoft Office Language Interface Pack 2007 Service Pack 3 (SP3)

2526307

32-bit

PowerPoint Viewer 2007 Service Pack 3 (SP3)

2526298

32-bit

Visio Viewer 2007 Service Pack 3 (SP3)

2526301

32-bit

Excel Viewer 2007 Service Pack 3 (SP3)

2526302

32-bit

Calendar Printing Assistant for Outlook 2007 Service Pack 3 (SP3)

2526294

32-bit

Microsoft Office InterConnect 2007 Service Pack 3 (SP3)

2526296

32-bit

Office Compatibility Pack Service Pack 3 (SP3)

2526297

32-bit

Microsoft Office Access Runtime and Data Connectivity Components 2007 Service Pack 3 (SP3)

2526310

32-bit

Windows SharePoint Services 3.0 Service Pack 3 (SP3) and of Windows SharePoint Services 3.0 Language Pack SP3

2526305

WSS 3.0: 32-bit; LPK: 32-bit ; WSS 3.0: 64-bit; LPK: 64-bit

Microsoft Expression Web 3 Service Pack 3 (SP3) and of Microsoft Expression Web Language Pack SP3

2575737

Expression Web : 32-bit; LPK: 32-bit

Known issues that you may experience when you install the 2007 Microsoft Office suite Service Pack 3 (SP3) and Windows SharePoint Services 3.0 SP3

2591067

n/a

List of all 2007 Office system Service Pack 3 and Windows SharePoint Services 3.0 Service Pack 3 packages

2591018

n/a

Technical details about the 2007 Microsoft Office System Service Pack 3 (SP3) releases

2591039

n/a

Technical details about the 2007 Microsoft Office Servers Service Pack 3 (SP3) releases

2591050

n/a

Technical details about the Windows SharePoint Services 3.0 Service Pack 3 (SP3) releases

2591054

n/a

SharePoint 2010: Como ejecutar un flujo de trabajo en varios elementos a la vez!

Una necesidad con la que me he encontrado hace poco es la de poder ejecutar un flujo de trabajo sobre varios elementos de una lista de forma simultanea. Por defecto, esta acción no se considera como “multi-elemento” en SharePoint 2010 por lo que necesariamente tenemos que buscar un workaround para conseguirlo…además, en mi caso resulta que no tengo posibilidad de desplegar lógica en el servidor por lo que necesariamente se tuvo que pensar en una solución con “cero” desarrollo…como habréis adivinado, esto nos lleva a pensar que posibilidades nos puede brindar SharePoint Designer 2010 (SPD 2010) para conseguir esto. Y efectivamente, es en el entorno de SPD 2010 junto con las posibilidades de la DataFormWebPart dónde podremos dar respuesta a esta necesidad…cómo siempre, alguien ya encontró el workaround que podéis encontrar en este enlace…solución efectiva diría yo.

SharePoint2010_thumb

SharePoint 2010: Apertura de ventanas modales y páginas desde acciones personalizadas (III)!

Siguiendo con la serie de posts en torno a la apertura de ventanas modales y páginas desde acciones personalizadas, en este nuevo artículo vamos a ver como podemos crear una acción personalizada de forma programática (que no declarativa) vinculada a una lista en exclusiva (algo que declarativamente no es posible de forma sencilla) y además desplegarla en nuestro sitio de SharePoint como una solución Sandbox lo que nos permitiría su uso en SharePoint Online en Office 365. Pero antes, os recuerdo los dos artículos previos de la serie:

Para abrir una ventana modal mediante una acción personalizada creada de forma programática:

  • En Visual Studio creamos un proyecto de tipo “Empty SharePoint Project”.
  • En el asistente de configuración especificamos como tipo de despliegue Sandbox.
  • Una vez creado el proyecto, a través del explorador de soluciones y situándonos en el nodo Feature añadimos una característica.
image image image
  • Configuramos la característica de forma adecuada, y le añadimos un Feature Event Receiver que es dónde vamos a añadir toda la lógica para la creación de la acción personalizada de forma programática.
  • Configuramos el método FeatureActivated() de la siguiente forma:
       1: public override void FeatureActivated(SPFeatureReceiverProperties properties)

       2: {

       3:     SPWeb spwWeb = (SPWeb)properties.Feature.Parent;        

       4:     SPList splList = spwWeb.Lists.TryGetList("Tareas");

       5:     SPUserCustomAction spucCustomAction = splList.UserCustomActions.Add();

       6:     spucCustomAction.Location = "CommandUI.Ribbon.ListView";

       7:     spucCustomAction.Sequence = 85;

       8:     spucCustomAction.Title = "Ayuda";

       9:     spucCustomAction.CommandUIExtension =

      10:         @"<CommandUIExtension>

      11:             <CommandUIDefinitions>

      12:                 <CommandUIDefinition Location=""Ribbon.ListItem.Actions.Controls._children"">

      13:                     <Button Id=""Ribbon.ListItem.Actions.Controls.HelpButton"" TemplateAlias=""o1"" Command=""HelpCommand"" 

      14:                     Image32by32=""http://demo2010a:100/sites/PortalIntranet/Documentos%20compartidos/Logo_Ayuda.gif"" 

      15:                     CommandType=""General"" LabelText=""Ayuda"" />

      16:                 </CommandUIDefinition>

      17:             </CommandUIDefinitions>

      18:             <CommandUIHandlers>

      19:                 <CommandUIHandler Command =""HelpCommand"" CommandAction=""javascript:SP.UI.ModalDialog.showModalDialog({url:'/_layouts/help.aspx',dialogReturnValueCallback: function(dialogResult, returnValue) { SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK) }})""/>

      20:             </CommandUIHandlers></CommandUIExtension>";

      21:     spucCustomAction.Update();

      22: }

  • Como vemos, la gracia de pode añadir una acción personalizada a una lista en concreta radica en crear una instancia de SPUserCustomAction que nos habilita para:
    • Añadir una acción personalizada a la lista deseada.
    • Especificar la ubicación de la acción a través de la propiedad Location.
    • Especificar el orden de aparición de la acción mediante la propiedad Sequence.
    • Y finalmente, y lo más importante, especificar la definición completa de la acción a través de la propiedad CommandUIExtension. Fijaros que aquí se está indicando la ubicación concreta de la acción (en la Ribbon de lista, en la sección Acciones), la imagen a utilizar (previamente cargada en el sitio o provisionada en el propio proyecto mediante un elemento de tipo módulo), y el comando que en este caso nos permite levantar la ventana modal especificando un bloque JavaScript que hace uso del Framework de ventanas modales.
  • Configuramos el método FeatureDeactivating() para realizar la correspondiente limpieza:
   1: public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

   2: {

   3:     SPWeb spwWeb = (SPWeb)properties.Feature.Parent;                

   4:     SPList splList = spwWeb.Lists.TryGetList("Tareas");

   5:     SPUserCustomActionCollection spuccCustomActionsConllection =

   6:         splList.UserCustomActions;

   7:     foreach (SPUserCustomAction spucCustomAction in spuccCustomActionsConllection)

   8:     {

   9:         if (spucCustomAction.Title == "Ayuda")

  10:         {

  11:             spucCustomAction.Delete();

  12:             break;

  13:         }

  14:     }

  15: }

  • Compilamos el proyecto y lo desplegamos en nuestro sitio de SharePoint. Comprobamos que la acción personalizada se ha añadido correcatamente en la Ribbon.
  • Finalmente comprobamos que la acción funciona como se espera:
image image

Referencias:

SharePoint 2010: Tokens que podemos usar en redirecciones!

A menudo cuando estamos añadiendo funcionalidad adicional en una solución SharePoint nos podemos encontrar con la necesidad de hacer redirecciones a ciertas páginas. Por ejemplo, desde una nueva opción de menú de elemento de lista navegar a una página concreta o a un formulario de edición de elemento que hayamos creado de forma personalizada. Pues bien, a la hora de especificar Urls de redirección a páginas de SharePoint disponemos de una serie de tokens que nos facilitan que las mismas sean + o – dinámicas. Estos tokens son:

  • ~sitecollection, para marcar que nos estamos refiriendo a una colección de sitios (SPSite).
  • ~site, para marcar que nos estamos refiriendo a un sitio de SharePoint (SPWeb).
  • {SiteUrl}, que nos proporciona la Url del sitio (de nuevo SPWeb).
  • {ListId}, que nos da acceso al ID de la lista sobre la que estamos definiendo la acción.
  • {ItemId}, para marcar que nos estamos refiriendo al ID del elemento seleccionado.
  • {ItemUrl}, que indica la Url del elemento actual.
  • {RecurrenceId}.

Por ejemplo, para especificar una redirección en una acción personaliza usando estos parámetros mediante un elemento de tipo <UrlAction> tendríamos:

   1: <UrlAction Url="~site/_layouts/CustomApplicationPage/CustomApplicationPage.aspx?ItemId={ItemId}&amp;ListId={listId}/>

De esta forma estaríamos haciendo una redirección a la página de aplicación CustomApplicationPage.aspx y pasando por parámetro el Id del elemento actual y el Id de la lista a la que pertenece.

SharePoint 2010: Controles delegados (I)!

Los controles de tipo delegado están pensados para cambiar el look & feel de un sitio de SharePoint ya que actúan como contenedores que encapsulan contenido por defecto (un conjunto de controles hijos). Lo interesante de estos controles, que SharePoint utiliza de una forma “intensiva” es que tenemos la posibilidad de “machacar” el contenido por defecto y añadir controles específicos a partir de desplegar la correspondiente feature. Algunos ejemplos de controles delegados disponibles a nivel de página maestra son: To Navigation Data Source, Left Navigation Data Source, Search Box, etc. Si editamos la página maestra de un sitio de SharePoint convencional (la v4.master de un sitio de tipo sitio de grupo) veremos que hay numerosas instancias de tipo <SharePoint: DelegateControl />. Este es un control que define un contenedor con un atributo ControlId único en la página o en la página maestra y que será reemplazado durante el renderizado de la misma por el control de servidor adecuado:

   1: <SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" 

   2: AllowMultipleControls="true"/>

   3: <SharePoint:DelegateControl runat="server" ControlId="GlobalNavigation" />

   4: <SharePoint:DelegateControl runat="server" ID="GlobalDelegate0" ControlId="GlobalSiteLink0" />

   5: <SharePoint:DelegateControl ControlId="GlobalSiteLink2" ID="GlobalDelegate2" Scope="Farm"

   6:  runat="server" />

   7: <SharePoint:DelegateControl runat="server" ControlId="PublishingConsole" 

   8: Id="PublishingConsoleDelegate">

   9: </SharePoint:DelegateControl><SharePoint:DelegateControl ControlId="GlobalSiteLink3" Scope="Farm" 

  10: runat="server" />

  11: <SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox" Version="4" />

  12: <SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" 

  13: Id="topNavigationDelegate"/>

Si editamos la página maestra v4.master con SharePoint Designer 2010 (SPD 2010) podremos ver estas instancias. Por ejemplo, podemos localizar fácilmente la relativa al control de búsqueda típico de SharePoint:

   1: <SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox" Version="4"/>

Para sobreescribir el comportamiento de un control delegado por defecto en tiempo de ejecución (por ejemplo el de búsqueda):

  • Por defecto este control delegado es reemplazado por el control nativo propio de SharePoint que en el caso de la versión server se encuentra definido en la clase Microsoft.SharePoint.Portal.WebControls.SearchBoxEx.
  • En Visual Studio 2010 creamos un proyecto de SharePoint 2010 de tipo vacío y elegimos como tipo de despliegue “Deploy as farm solution”.
  • Añadimos al proyecto un elemento de tipo vacío, de forma que se crea la correspondiente feature que configuramos de forma adecuada (título, descripción, propiedades, etc).
  • Configuramos el archivo Elements.xml de la siguiente forma:
   1: <?xml version="1.0" encoding="utf-8"?>

   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

   3:     <Control Id="SmallSearchInputBox"

   4:              Sequence="10"

   5:              ControlAssembly="$SharePoint.Project.AssemblyFullName$"

   6:              ControlClass="SPDelegateSearchControl.CustomSearchControl" />

   7:     <Control Id="SmallSearchInputBox"

   8:              Sequence="5"

   9:                ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx"

  10:                ControlAssembly="Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">

  11:         <Property Name="FrameType">None</Property>

  12:         <Property Name="DropDownMode">ShowDD</Property>

  13:         <Property Name="TextBoxWidth">200</Property>

  14:         <Property Name="ShowAdvancedSearch">true</Property>

  15:         <Property Name="QueryPromptString">Your search here...</Property>

  16:         <Property Name="SearchBoxTableClass">search-box</Property>

  17:     </Control>

  18: </Elements>

  • Como vemos, estamos añadiendo dos posibles controles delegados relativos a la caja de búsqueda de SharePoint (SmallSearchInputBox):
    • El primero de ellos haría referencia a una implementación propia del control de búsqueda.
    • El segundo, lo que hace es añadir configuraciones adicionales al control de búsqueda existente por defecto en la plataforma.
    • El atributo Sequence le va a indicar a SharePoint que control usar, teniendo en cuenta que considerará aquel control que tenga un valor mñas bajo para dicho atributo.

Hacemos el despliegue del proyecto y comprobamos que la personalización del control delegado se ha aplicado

image image image

 

Algunas referencias sobre controles delegados:

SharePoint 2010: Manejadores de eventos síncronos vs asíncronos (I)!

Como sabéis, desde SharePoint 2007 contamos con la posibilidad de añadir cierta lógica a nuestras soluciones de SharePoint mediante los denominados manejadores de eventos que no dejan de ser clases que heredan de clases base especificas a ciertos eventos de SharePoint: SPItemEventReceiver para eventos relativos a elementos de lista / biblioteca de documentos, SPListEventReceiver para eventos relativos a listas, SPFeatureReceiver para eventos relativos a características, etc. Todas estas clases, salvo en el caso de SPEmailEventReceiver y SPFeatureReceiver, heredan de una misma clase base SPEventReceiverBase que es la que proporciona todos los métodos que normalmente sobreescribiremos en nuestros manejadores. En SharePoint vamos a tener dos tipos de manejadores de eventos:

  • Los denominados síncronos o “Before”:
    • Aquellos que tienen lugar antes de que ocurra un evento y que por lo tanto son útiles para realizar validaciones, chequeos o cancelaciones antes de que SharePoint escriba información en la BD de contenidos.
    • Estos eventos  se ejecutan en el mismo thread que la acción actual.
  • Los asíncronos o After”:
    • Aquellos que ocurren después de que SharePoint haga un “commit” de los datos en la BD de contenidos de manera que la operación no puede ser cancelada.
    • En este caso, la ejecución se realiza en otro thread respecto a la acción actual aunque es posible forzar una ejecución síncrona jugando con la propiedad Synchronization.

SharePoint 2010: Anatomía de un proyecto de WebPart en VS 2010!

Sin duda, a la hora de crear artefactos para SharePoint 2010 como WebParts, manejadores de eventos, etc la ayuda que nos brindan las Visual Studio 2010 Tools para SharePoint es fundamental. Ahora bien, aunque el uso de las herramientas nos ahorre mucho trabajo y simplifique las tareas a realizar es importante tener una idea clara de lo que estamos haciendo y saber que elementos forman parte de uno de estos artefactos. Cuando añadimos un elemento de tipo WebPart por ejemplo en un proyecto de Visual Studio para SharePoint, automáticamente se crea un SPI o SharePoint Project Item que contiene los elementos mínimos para poder desplegar una WebPart en nuestros sitios de SharePoint y que esté plenamente operativa:

image

  • Archivo de manifiesto, clave en este caso para provisionar el archivo .webpart que contiene toda la definición de una WebPart como el título, la descripción, etc. En este archivo son destacables:
    • La declaración del tipo .NET que se corresponde con la WebPart (definido en <metaData>) que en este caso está definido como un nombre completo (Full name) a través de la propiedad name que en este caso tiene el valor SPLINQWP.SPLINQToSPCRWP.SPLINQToSPCRP junto con el nombre del ensamblado que se especifica mediante $SharePoint.Project.AssemblyFullName$ que es automáticamente reemplazado por VS 2010 por el nombre del ensamblado durante el proceso de despliegue.
   1: <?xml version="1.0" encoding="utf-8"?>

   2: <webParts>

   3:   <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

   4:     <metaData>

   5:       <type name="SPLINQWP.SPLINQToSPCRWP.SPLINQToSPCRWP, $SharePoint.Project.AssemblyFullName$" />

   6:       <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>

   7:     </metaData>

   8:     <data>

   9:       <properties>

  10:           <property name="ChromeType" type="chrometype">TitleAndBorder</property>

  11:           <property name="Title" type="string">LINQ To SharePoint WP</property>

  12:           <property name="TitleIconImageUrl" type="string">_layouts/images/SPLINQWP/Feature_Icon_2.jpg</property>

  13:           <property name="Description" type="string">LINQ To SharePoint WebPart</property>

  14:           <property name="CatalogIconImageUrl" type="string">_layouts/images/SPLINQWP/Feature_Icon_2.jpg</property>

  15:           <property name="AllowEdit" type="bool">True</property>

  16:           <property name="AllowClose" type="bool">False</property>

  17:           <property name="AllowHide" type="bool">False</property>

  18:           <property name="AllowMinimize" type="bool">False</property>

  19:           <property name="AllowZoneChange" type="bool">False</property>

  20:           <property name="AllowConnect" type="bool">False</property>

  21:           <property name="ExportMode" type="exportmode">All</property>

  22:       </properties>

  23:     </data>

  24:   </webPart>

  25: </webParts>

  • Archivo de manifiesto “Elements.xml” en el que definimos como vamos a provisionar la WebPart. Más en concreto, como vamos a provisionar el archivo .webpart anterior en la galería de webparts y también en qué categoría se va a ubicar:
   1: <?xml version="1.0" encoding="utf-8"?>

   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/" >

   3:   <Module Name="SPLINQToSPCRWP" List="113" Url="_catalogs/wp">

   4:     <File Path="SPLINQToSPCRWP\SPLINQToSPCRWP.webpart" Url="SPLINQToSPCRWP.webpart" Type="GhostableInLibrary" >

   5:       <Property Name="Group" Value="BootCamp Costa Rica" />

   6:     </File>

   7:   </Module>

   8: </Elements>

  • Una clase que representa a la WebPart y que hereda de la clase base WebPart que como tal modela un control personalizado de ASP.NET. La definición de esta clase, para una WebPart de tipo clásico o una WebPart de tipo visual es como sigue:
   1: using System;

   2: using System.ComponentModel;

   3: using System.Web;

   4: using System.Web.UI;

   5: using System.Web.UI.WebControls;

   6: using System.Web.UI.WebControls.WebParts;

   7: using Microsoft.SharePoint;

   8: using Microsoft.SharePoint.WebControls;

   9:  

  10: namespace SPLINQWP.SPLINQToSPCRWP

  11: {

  12:     [ToolboxItemAttribute(false)]

  13:     public class SPLINQToSPCRWP : WebPart

  14:     {

  15:         // Visual Studio might automatically update this path when you change the Visual Web Part project item.

  16:         private const string _ascxPath = @"~/_CONTROLTEMPLATES/SPLINQWP/SPLINQToSPCRWP/SPLINQToSPCRWPUserControl.ascx";

  17:  

  18:         protected override void CreateChildControls()

  19:         {

  20:             Control control = Page.LoadControl(_ascxPath);

  21:             Controls.Add(control);

  22:         }

  23:     }

  24: }

  • Como vemos, uno de los puntos clave de la clase es la sobreescritura del método CreateChildControls() que como en cualquier control ASP.NET nos permite definir los controles web que constituyen la WebPart. En este caso, al tratarse de una WebPart visual tendremos un control definido a partir del user control que constituye la parte visual de la WebPart.
  • Un archivo de tipo user control para el caso de WebParts visuales.

Hasta aquí los elementos clave que forman parte de la WebPart a desplegar…pero, ¿cómo se despliega y hace disponible esta WebPart? Pues a través del correspondiente .WSP y de la correspondiente feature:

  • Si examinamos de nuevo la solución creada en Visual Studio 2010 veremos que tenemos un nodo Package en el que se define la plantilla del .WSP a generar. Es en esta definición dónde se indica que la WebPart se empaqueta como un .WSP indicando aspectos como:
    • La ubicación de despliegue de la WebPart (en este caso la GAC o Global Assembly Cache)
    • El “nombre fuerte” o strong name del ensamblado: nombre, versión, cultura y PublicKeyToken. Este strong name es el que permite añadir el ensamblado como un control seguro,
  • Y todo esto lo hace Visual Studio 2010 automáticamente por nosotros:
   1: <Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="7ea4b87f-de64-46ec-9208-ac5b11d184b3" SharePointProductVersion="14.0">

   2:   <Assemblies>

   3:     <Assembly Location="SPLINQWP.dll" DeploymentTarget="GlobalAssemblyCache">

   4:       <SafeControls>

   5:         <SafeControl Assembly="SPLINQWP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2ebe5d86e0efc3de" Namespace="SPLINQWP.SPLINQToSPCRWP" TypeName="*" />

   6:       </SafeControls>

   7:     </Assembly>

   8:   </Assemblies>

   9:   <TemplateFiles>

  10:     <TemplateFile Location="CONTROLTEMPLATES\SPLINQWP\SPLINQToSPCRWP\SPLINQToSPCRWPUserControl.ascx" />

  11:     <TemplateFile Location="Images\SPLINQWP\Feature_Icon_2.jpg" />

  12:   </TemplateFiles>

  13:   <FeatureManifests>

  14:     <FeatureManifest Location="SPLINQWP_SPLINQToSharePointWPFeature\Feature.xml" />

  15:   </FeatureManifests>

  16: </Solution>

  • La correspondiente Feature o Característica cuya activación hace posible que dispongamos de la WebPart para poder usar en nuestros sitios. Esta característica define la ubicación del archivo de manifiesto de la WebPart y del archivo .webpart.
   1: <Feature xmlns="http://schemas.microsoft.com/sharepoint/" Title="SP LINQ To SharePoint WebPart" Description="SP LINQ To SharePoint WebPart" Id="1e918292-9c18-4d06-9ede-b079d6e017ae" ImageUrl="SPLINQWP/Feature_Icon_2.jpg" Scope="Site">

   2:   <ElementManifests>

   3:     <ElementManifest Location="SPLINQToSPCRWP\Elements.xml" />

   4:     <ElementFile Location="SPLINQToSPCRWP\SPLINQToSPCRWP.webpart" />

   5:   </ElementManifests>

   6: </Feature>

image image