InfoPath como aplicación es capaz de generar documentos XML que contienen no solo la información también la estructura del mismo.

Utilizando la herramienta XSD.exe es posible generar una clase que facilite manipular dicha información (http://msdn.microsoft.com/en-us/library/bb251017.aspx). Sin embargo, es específica para cada documento.

En muchas oportunidades sucede que se requiere codificar (por ejemplo un flujo de trabajo), para múltiples documentos y formatos.

Para facilitar estas actividades, se me ocurrió definir una clase que administre genéricamente el contenido de documentos InfoPath.

Esta clase recibe un elemento de una biblioteca de documentos InfoPath de SharePoint y carga el documento en memoria para facilitar su manipulación.

La definición de la clase.

Comencemos con la lista de importaciones y variables necesarias.

Imports System.Xml.Serialization

Imports System.Xml

”’ <summary>

”’ Permite manipular el contenido de un documento de InfoPath en algo fácilmente accesible por código

”’ </summary>

”’ <remarks>Carga el contenido del documento, adjunto a una biblioteca de documentos de MOSS

”’ y crea listas fácilmente accesibles tanto de los atributos como de los valores (elementos)

”’ </remarks>

Public Class InfoPathConverter

    ”’ <summary>

      ”’ Documento conteniendo todo el documento InfoPath

    ”’ </summary>

    ”’ <remarks></remarks>

    Dim xDoc As XDocument = Nothing

    ”’ <summary>

    ”’ Lista de atributos

    ”’ </summary>

    ”’ <remarks></remarks>

    Dim atrs As Dictionary(Of String, XAttribute)

    ”’ <summary>

    ”’ lista de valores (elementos)

    ”’ </summary>

    ”’ <remarks></remarks>

    Dim els As Dictionary(Of String, XElement)

Una de las características que me suelen ser necesarias es la de asegurarme que existan ciertas propiedades y atributos en el documento ya que son utilizados en la lógica del flujo.

Por ello, la clase expone 2 propiedades para contener los atributos y los campos que son requeridos.

    ”’ <summary>

    ”’ Lista de nombres de atributos requeridos en el documento

    ”’ </summary>

    ”’ <remarks></remarks>

    Private mAtributes As List(Of String)

      ”’ <summary>

      ”’ Define que atributos son necesarios en el documento para considerarlo válido

      ”’ </summary>

      ”’ <value></value>

      ”’ <returns></returns>

      ”’ <remarks></remarks>

    Public ReadOnly Property AttributesNeeded() As List(Of String)

        Get

            If mAtributes Is Nothing Then

                mAtributes = New List(Of String)

                mAtributes.Add("Etapa")

            End If

            Return mAtributes

        End Get

    End Property

 

      Private mFieldsNeeded As List(Of String)

      ”’ <summary>

      ”’ Define que campos son necesarios en el documento para considerarlo válido

      ”’ </summary>

      ”’ <value></value>

      ”’ <returns></returns>

      ”’ <remarks></remarks>

    Public ReadOnly Property FieldsNeeded() As List(Of String)

        Get

            If mFieldsNeeded Is Nothing Then

                mFieldsNeeded = New List(Of String)

            End If

            Return mFieldsNeeded

        End Get

    End Property

Cargando el documento en memoria.

El método getDocumentContent recibe entonces el item de la biblioteca de documentos, obtiene el documento XML y carga en diccionarios los atributos y propiedades

    ”’ <summary>

    ”’ Carga en las listas el contenido del documento InfoPath

    ”’ </summary>

      ”’ <param name="item">Item de la biblioteca de docuemntos, conteniendo el mismo</param>

      ”’ <remarks>Carga el contenido del documento, adjunto a una biblioteca de documentos de MOSS

    ”’ y crea listas fácilmente accesibles tanto de los atributos como de los valores (elementos)

    ”’ </remarks>

      Sub getDocumentContent(ByVal item As SPListItem)

            ‘La propiedad File expone el documento InfoPath

            Dim xtextr As New XmlTextReader(item.File.OpenBinaryStream)

            ‘Se carga entonces el documento desde el Stream

            xDoc = XDocument.Load(xtextr)

            ‘Obtiene los atributos

            atrs = (From x As XAttribute In xDoc.Root.Attributes).ToDictionary( _

            Of String)(Function(x) x.Name.LocalName.ToUpper)

            ‘ Evalúa si todos los atributos requeridos están pesentes

            For Each s As String In AttributesNeeded

                  Dim lookFor As String = s.ToUpper

                  If (From a As XAttribute In atrs.Values _

                    Where a.Name.LocalName.ToUpper = lookFor).ToArray.Length < 1 Then

                        Throw New Exception("Formulario inválido: le falta el atributo " & s)

                  End If

            Next

            ‘ Evalúa lo mismo para los campos (Elements)

            els = (From v As XElement In xDoc.Root.Elements).ToDictionary( _

            Of String)(Function(v) v.Name.LocalName.ToUpper)

            For Each s As String In FieldsNeeded

                  Dim lookFor As String = s.ToUpper

                  If (From a As XElement In els.Values _

                    Where a.Name.LocalName.ToUpper = lookFor).ToArray.Length < 1 Then

                        Throw New Exception("Formulario inválido: le falta el campo " & s)

                  End If

            Next

      End Sub

Teniendo el documento en memoria, se pueden exponer los valores y asignarles nuevos con estos métodos:

    ”’ <summary>

    ”’ Cambia el valor de un atributo

    ”’ </summary>

    ”’ <param name="what">Nombre del atributo</param>

    ”’ <param name="newValue">Nuevo Valor</param>

    ”’ <remarks></remarks>

    Sub ChangeAttribute(ByVal what As String, ByVal newValue As String)

        If atrs.ContainsKey(what.ToUpper) Then

            atrs(what.ToUpper).Value = newValue

        End If

    End Sub

    ”’ <summary>

    ”’ Obtiene el valor de uhn atributo

    ”’ </summary>

    ”’ <param name="what">Nombre del atirbuto</param>

    ”’ <returns>Contenido del mismo (siempr como cadena de caracteres) o valor nulo si no existe

    ”’ </returns>

    ”’ <remarks></remarks>

    Function ReadAttribute(ByVal what As String) As String

        If atrs.ContainsKey(what.ToUpper) Then

            Return atrs(what.ToUpper).Value

        Else

            Return Nothing

        End If

    End Function

    ”’ <summary>

    ”’ Cambia el valor de un elemento

    ”’ </summary>

    ”’ <param name="what">Nombre del elemento</param>

    ”’ <param name="newValue">Valor a asignar</param>

    ”’ <remarks></remarks>

    Sub ChangeValue(ByVal what As String, ByVal newValue As String)

        If els.ContainsKey(what.ToUpper) Then

            els(what.ToUpper).Value = newValue

        End If

    End Sub

    ”’ <summary>

    ”’ Obtiene le valor de un elemento

    ”’ </summary>

    ”’ <param name="what">Nombre del elemento a leer</param>

    ”’ <returns>Valor del elemento (siempre como cadena de caracteres), o valor nulo si no existe

    ”’ </returns>

    ”’ <remarks></remarks>

    Function ReadValue(ByVal what As String) As String

        If els.ContainsKey(what.ToUpper) Then

            Return els(what.ToUpper).Value

        Else

            Throw New KeyNotFoundException("El campo " & what & " no se encuentra en el documento")

        End If

    End Function

Guardando cambios.

Finalmente ento0nces, con un método Save, se puede guardar en la lista de origen… o en otra. Para ello, se le envía al método el ListItem que contendrá el documento.

    ”’ <summary>

    ”’ Guarda el contenido de los valores y atributos en el documento InfoPath actualizando los mismos 

    ”’ </summary>

    ”’ <param name="item"></param>

    ”’ <remarks></remarks>

    Public Sub Save(ByVal item As SPListItem)

        item.File.CheckOut()

        Dim memoryStream As New IO.MemoryStream()

        Dim sett As New XmlWriterSettings

        sett.Encoding = System.Text.Encoding.UTF8

        sett.OmitXmlDeclaration = False

        Dim xmlTextWriter As XmlWriter = XmlWriter.Create(memoryStream, sett)

        xDoc.Save(xmlTextWriter)

        xmlTextWriter.Flush()

        memoryStream.Position = 0

        item.File.SaveBinary(memoryStream.GetBuffer)

        item.File.CheckIn("")

    End Sub

Si si, ya sé. quieres verlo completo. Pues aquí está la clase entera. https://blogvisionarios.com/ES/dseara/Archivos/InfoPathConverter.zip

0 Shares:
Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

You May Also Like