Autor : Gustavo Velez Para : www.gavd.net/servers/ Fecha : 30-05-2005 Versión : 1.0.0 WebServices Parte 2 XML Para garantizar la integración de WSS y SharePoint con otros tipos de aplicaciones, un sistema de WebService es instalado por defecto con el Portal. Los WebServices proveen una amplia gama de funcionalidad, pero no todas las partes de SharePoint se pueden alcanzar desde sus WebServices. En el caso de que sea necesario realizar alguna función que no exista en una de los WebServices por defecto, siempre es posible crear uno propio. Segunda parte de la serie de artículos sobre WebServices y SharePoint que suministra información sobre como manipular los resultados de XML que un WebService provee. El ejemplo de este articulo continua con el código de la parte 1. WebServices y XML Los WebServices de SharePoint, como todo WebService, están basados en SOAP (Simple Object Access Protocol). La mayoría de los métodos de los WebServices instalados por defecto en SharePoint retornan un documento de XML, con un NameSpace asociado a el, lo que permite el uso de las clases para XML de DotNet. Cuando este no es el caso (vea el ejemplo en este articulo), es posible o usar una transformación, o complementar el URI para poderlo tratar como un documento XML completo. Aplicación para Windows (Continuación) La primera parte de la serie de artículos daba instrucciones para hacer un programa de Windows que puede leer las plantillas disponibles en un sitio, utilizando el correspondiente WebService. La continuación del código muestra como encontrar las Listas de un sitio. 1 Amplíe la interfase de la aplicación, de tal forma que el usuario tenga un botón para encontrar las Listas del sitio definido, y un TextBox para definir el nombre de la Lista de la que se quieren ver los Elementos
2 En el evento del botón Listas, primero hay que añadir código para definir una instancia del WebService y para darle las credenciales del usuario: wv01.lists MyListsService = new SpsWebService_01.wv01.Lists(); MyListsService.Credentials = new NetworkCredential(this.txtUsuario.Text, this.txtcontrasena.text, this.txtdominio.text); 3 Haga el WebService independiente del URL que se definió en la referencia, de tal forma que se pueda usar para encontrar resultados de otros sitios: MySitesService.Url = this.txturl.text + "_vti_bin/sites.asmx"; 4 Una referencia al método GetListCollection devuelve la información sobre la colección de Listas del sitio en la forma de una colección de XmlNode, que se puede leer usando un estamento foreach MyListsService.Url = this.txturl.text + "_vti_bin/lists.asmx"; XmlNode MyNode = MyListsService.GetListCollection(); foreach(system.xml.xmlnode MyXmlnode in MyNode) this.txtresultado.text += MyXmlnode.Attributes["Title"].Value + "\r\n"; 5 Cuando el usuario copia el nombre de una de las listas en el espacio indicado, puede hacer uso de tres botones para encontrar los elementos de la lista en tres maneras diferentes: como XML, usando un DataSet o utilizando XPath. 6 Para ver el resultado de la búsqueda de los elementos como XML, primero se definen algunas variables que contendrán la consulta, las opciones de la consulta y los campos que se desean ver. En el ejemplo se desean ver todos los campos del resultado, y todos los resultados de la Lista, por lo que las variables son inicializadas, pero no contienen ningún tipo de filtro.
XmlDocument MyXmlDoc = new XmlDocument(); XmlNode MyNodeQuery = MyXmlDoc.CreateNode(XmlNodeType.Element,"Query",""); XmlNode MyNodeViewFields = MyXmlDoc.CreateNode(XmlNodeType.Element,"ViewFields",""); XmlNode MyNodeQueryOptions = MyXmlDoc.CreateNode(XmlNodeType.Element,"QueryOptions",""); XslTransform myxslt = new XslTransform(); MemoryStream mymemstream = new MemoryStream(); El método GetListItems es el que provee los resultados deseados: XmlNode myxmlnode = MyListsService.GetListItems(this.txtList.Text, null, MyNodeQuery, MyNodeViewFields, null, MyNodeQueryOptions); El resultado es guardado en un XmlDocument, y un StreamReader se encarga de convertirlo en texto leíble para la interfase: myxslt.load("../../a.xslt"); MyXmlDoc.LoadXml("<?xml version='1.0'?>" + myxmlnode.outerxml); myxslt.transform(myxmldoc, null, mymemstream, null); mymemstream.position = 0; StreamReader mystreamreader = new StreamReader(myMemStream); this.txtresultado.text += mystreamreader.readtoend(); La transformación XSLT contenida en un archivo separado convierte el texto de XML en una forma que pueda ser interpretada más fácilmente por los usuarios. La transformación solamente cambia la sangría, sin cambiar la forma en que los datos son presentados: <?xml version = "1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="node() @*"> <xsl:copy> <xsl:apply-templates select="node() @*"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
7 Los datos devueltos por el WebService se pueden introducir en un DataSet para poderlos usar en una DataGrid, o cualquier otro control que aplique la interfase de IBind. En este caso, primero hay que crear un XmlDataDocument y un DataSet que utilizara sus meta-datos: XmlDataDocument myxmldatadocument = new XmlDataDocument(); DataSet MyDataSet = myxmldatadocument.dataset; Luego de obtener el XmlNode utilizando el método GetListItems de la misma forma que en el punto anterior, un XmlTextReader provee el contenido al DataSet y un bucle puede leer los datos en la pantalla (aquí se puede usar el DataSet para otras cosas, como por ejemplo, para llenar una DataGrid ): XmlTextReader MyXmlTextReader = new XmlTextReader(myXmlNode.OuterXml, XmlNodeType.Element, null); MyDataSet.ReadXml(MyXmlTextReader); foreach(datarow myrow in MyDataSet.Tables[1].Rows) this.txtresultado.text += myrow["ows_basename"] + " - " + myrow["ows_serverurl"] + "\r\n"; Este método crea dos tablas in de DataSet: la primera conteniendo la cantidad de records en la Lista, y la segunda conteniendo los records mismos. Cada columna de listas utiliza un prefijo ows_, como se puede ver en el resultado del XML, que es necesario de respetar para poder leer los datos de la DataSet. 8 Si es necesario leer los resultados del WebService usando directamente XML, luego de construir el XMLNode con los resultados de GetListItems como se indica en anteriormente, se puede crear una consulta de XPath que entregue todos los resultados sin filtrar, de la forma: string MyXpathQuery = "//*[local-name() = 'data' and namespace-uri() = 'urn:schemas-microsoftcom:rowset']/*[local-name() = 'row' and namespace-uri() = '#RowsetSchema']"; Y luego navegar por todos los nudos usando un XmlNodeList :
XmlNodeList MyNodes = myxmlnode.selectnodes(myxpathquery); for(int i = 0; i < MyNodes.Count; i++) this.txtresultado.text += MyNodes[i].Attributes["ows_BaseName"].Value + " - " + MyNodes[i].Attributes["ows_BaseName"].Value + "\r\n"; Note la diferencia en la ruta al documento, en comparación con el uso de una DataSet: porque aquí se usa un filtro genérico en la consulta, las rutas a los documentos no aparecen en la pantalla. Hay varias otras formas de utilizar el documento XML, por ejemplo usando consultas más refinadas que entreguen solamente los campos necesarios, o utilizar un XPathNavigator o, inclusive, utilizar una XmlSerialization. Tenga en cuenta que un DataSet puede ser un objeto bastante grande que puede usar bastante memoria de los servidores y que los métodos de XML no son fáciles de utilizar, en el momento de tomar una decisión sobre el método a utilizar. El último método, utilizando XML también puede utilizar bastante memoria usándolo en la forma del ejemplo, pero puede ser la manera indicada de trabajar si solamente se necesita encontrar uno de los ítems de la lista. En este caso, la consulta y el método a utilizar son: string MyXpathQuery = "//*[@ows_title='thanksgiving']" XmlNode MyNode = myxmlnode.selectsinglenode(myxpathquery)