mercredi 16 juin 2010

Utiliser un extended object pour obtenir des node xml

Dans mon travail nous affichons quasiment toutes nos données via xsl.

Parfois au milieu d'un XSL on a besoin de certaine donnée qui n'existe pas dans un fichier XML mais qui sont le résultats de l'appel d'une fonction.

1/ Créer votre objet qui possède une méthode qui appelle vos webservice

[sourcecode language="csharp"]
public class MaClasseCliente{
public XmlNode MaFonctionQuiFaitQQCH(string unParametre){
MonObjetResultat obj = MaClasse.MaMethode(unParametre);
XmlSerializer ser = new XmlSerializer(obj.GetType());
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter(sb);
ser.Serialize(writer, obj);
XmlDocument doc = new XmlDocument();
doc.LoadXml(sb.ToString());
return doc.LastChild;
}
}
[/sourcecode]

Ici donc je sérialize l'objet (qui est doit etre Serializable) dans un StringBuilder.
Je mets tout ça dans un XmlDocument, puis je retourne le LastChild du Document (le document a 2 enfants : la déclaration xml, et l'élément racine, donc LastChild me permet de récupérer facilement les données).

2/ On envoi l'objet au xml
Ma balise dans mon .aspx

[sourcecode language="html"]
<asp:Xml runat="server" TransformSource="style.xslt" DocumentSource="data.xml"/>
[/sourcecode]

Dans mon code behind (.aspx.cs)

[sourcecode language="csharp"]
XsltArgumentList arguments = new XsltArgumentList();
arguments.AddExtensionObject("MonObjet",new MaClasseCliente());
xml.TransformArgumentList = arguments;[/sourcecode]

3/Mon xslt maintenant
La balise xsl:stylesheet (en haut de la fiche de style)

[sourcecode language="html"]
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:monObjetXslt="MonObjet">
[/sourcecode]

Le "xmlns:ms" c'est fait pour pouvoir utiliser une fonction spécifique au moteur XPath de ms
Et maintenant l'appel magique :)

[sourcecode language="html"]
<xsl:variable name="monObjet" value="ms:node-set(monObjetXslt:MaFonctionQuiFaitQQCH(//UneBaliseQueJeVeutEnParametre))"/>
<xsl:value-of select="$monObjet/Root/UneBalise"/>
[/sourcecode]

"ms:node-set" est comme un eval d'un objet en tant que données xml.

A faire attention :
-On ne peut avoir en paramètre que certain type de donnée : chaine, booleen, nombre, node ou liste de node
-Il faut un nombre fixe de paramètres (oubliez les "params" pour pouvoir faire de la reflection et appeler tout vos objets)
-Attention au namespaces lors de la sérialisation .La seule solution que j'ai trouvé a été de faire des Replace sur le InnerXml du XmlDocument.
-Attention , comme dans tout dev, a faire des appel en N+1 au méthode qui utilise des I/O (ex : requête SQL dans une boucle = mal). Vaut mieux tout requêter au début en une seule fois, les I/O sont très gourmand en ressource et temps d'attente.

Référence :
- addextensionobject

Aucun commentaire:

Enregistrer un commentaire