Renaud Harduin
XMLA Trivia : Découverte du XMLA
Le XMLA (XML for Analysis) est un langage normalisé par plusieurs éditeurs BI pour simplifier l'accès aux données aux cubes et aux métadonnées des bases multidimensionnelles.
Par Renaud Harduin publié le 25/05/2008 à 11:57, lu 1480 fois, 5 pages
 2 | Discussion autour du XMLA
Le XMLA est sensé être l'espéranto des bases muldimensionnelles. Microsoft, Hypérion et SAS ont proposé ce langage afin d'unifier les API d'accès.
Depuis lors, Microsoft a beaucoup avancé sur le sujet. Par défaut, le SSAS est un listener XMLA :
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image002.gif
 
(source msdn)
Le service expose 2 méthodes :
  1. Discover qui permet notamment d'explorer les métadonnées
  2. Execute qui permet d'exécuter des commandes (requêtes / process ...)
Le service renvoie alors des réponses en XMLA ce qui nous permet d'écrire des applications faiblement couplées.
De manière simple vous pouvez exécuter des requêtes XMLA dans SSMS :
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image003.png
 
Ceci dit, afin d'aider à la bonne compréhension du XMLA, je me suis dit que j'allais me servir comme support d'une application (XMLA Viewer, cf. code source de l'article) dont le simple but est d'afficher le retour XMLA. Nous extrairons uniquement dans le flux les éléments de données, l'affichage de base étant spartiate.Par exemple, si vous exécutez la requête de découverte suivante :

<Discover xmlns="urn:schemas-microsoft-com:xml-analysis">

  <RequestType>DISCOVER_DATASOURCES</RequestType>

  <Restrictions></Restrictions>

  <Properties></Properties>

</Discover>

Vous allez recueillir:

<return xmlns="urn:schemas-microsoft-com:xml-analysis">

  <root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" 

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:schema targetNamespace="urn:schemas-microsoft-com:xml-analysis:rowset" 

                xmlns:sql="urn:schemas-microsoft-com:xml-sql" elementFormDefault="qualified">

      <xsd:element name="root">

        <xsd:complexType>

          <xsd:sequence minOccurs="0" maxOccurs="unbounded">

            <xsd:element name="row" type="row" />

          </xsd:sequence>

        </xsd:complexType>

      </xsd:element>

      <xsd:simpleType name="uuid">

        <xsd:restriction base="xsd:string">

          <xsd:pattern value="[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}" />

        </xsd:restriction>

      </xsd:simpleType>

      <xsd:complexType name="xmlDocument">

        <xsd:sequence>

          <xsd:any />

        </xsd:sequence>

      </xsd:complexType>

      <xsd:complexType name="row">

        <xsd:sequence>

          <xsd:element sql:field="DataSourceName" name="DataSourceName" type="xsd:string" />

          <xsd:element sql:field="DataSourceDescription" name="DataSourceDescription" 

                       type="xsd:string" minOccurs="0" />

          <xsd:element sql:field="URL" name="URL" type="xsd:string" minOccurs="0" />

          <xsd:element sql:field="DataSourceInfo" name="DataSourceInfo" type="xsd:string" 

                       minOccurs="0" />

          <xsd:element sql:field="ProviderName" name="ProviderName" type="xsd:string" />

          <xsd:element sql:field="ProviderType" name="ProviderType" type="xsd:string" 

                       minOccurs="0" maxOccurs="unbounded" />

          <xsd:element sql:field="AuthenticationMode" name="AuthenticationMode" 

                       type="xsd:string" minOccurs="0" />

        </xsd:sequence>

      </xsd:complexType>

    </xsd:schema>

    <row>

      <DataSourceName>FREL11166\BILAB2005</DataSourceName>

      <DataSourceDescription />

      <URL />

      <DataSourceInfo />

      <ProviderName>Microsoft Analysis Services</ProviderName>

      <ProviderType>MDP</ProviderType>

      <ProviderType>TDP</ProviderType>

      <ProviderType>DMP</ProviderType>

      <AuthenticationMode>Authenticated</AuthenticationMode>

    </row>

  </root>

</return>

Le premier bloc contient le XSD streamé “inline” à la réponse. Il contient le schéma de la vraie réponse. Dans le cas présent, nous allons récupérer un jeu de ligne contenant :
  1. Le source
  2. Sa description
  3. Son url (si provider HTTP)
  4. Le provider
  5. Ce que supporte le provider (provider type)
  6. Le mode d'authentification...
Le deuxième bloc contient les données sous la forme d'éléments « row » dans le « root ». Nous itérons dans ceux-ci pour avoir nos résultats.
Aussi, le projet se présente sous un winform avec des boutons simples appelant tel ou tel XMLA, et un DataGridView pour le rendu des données (les éléments de types « row » ).
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image004.png
 
A ce stade, il s'agit alors de se connecter au provider XMLA (SSAS) et c'est là ou cela devient intéressant. Microsoft nous fournit un client XMLA avec SQL Server 2005 accessible sous :
C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies\Microsoft.AnalysisServices.XMLA.dll
Cette assembly une fois référencée sous Microsoft.AnalysisServices.XMLA nous permet d'accéder à la classe XmlaClient qui dispose des méthodes d'accès au service:
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image005.png
 
Nous créons donc un privé :

private XmlaClient _xmlaWS = new XmlaClient();

Que nous connectons avec une chaine de connexion classique au setup de l'application :

_xmlaWS.Connect(@"LOCALHOST\BILAB2005");

Les template de XMLA sont nommés de manière explicite de sorte que vous puissiez les consulter en parallèle du code (dans un dossier. /XMLA/).
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image006.png
 
Vous trouverez pour chacune des requêtes le résultat XMLA retourné tel quel.
Reprenons l'exemple de la découverte des datasources. La requête est sous 0010_D_Datasources.xmla.Lors du clic sur le bouton, nous déclenchons :

 

private void button1_Click(object sender, EventArgs e)

{

 

    XmlDocument xmlDom = new XmlDocument();

    string result = "";

    string command = File.ReadAllText(@".\XMLa\0010_D_Datasources.xmla");

 

Nous allons chercher le XMLA dans le fichier adéquat pour appeler la méthode « send » du webservice :

    Debug.WriteLine(_xmlaWS.GetConnectionState(true).ToString());

    string  xmlaResult = _xmlaWS.Send(command, null);

    xmlDom.LoadXml(xmlaResult);

    XmlNodeList nl = xmlDom.GetElementsByTagName("row");

    this.renderData(nl); 

}

Une fois le XML récupéré dans la chaîne xmlaResult, nous la parsons pour ne récupérer que les “<row>”.Pour simplifier nous passons la liste de noeuds à la méthode renderData() dont l'objet est de recréer un dataset à partir des données extraites, afin d'afficher les données dans un gridview.

private void renderData(XmlNodeList nl)

{

    DataSet ds = new DataSet();

    DataTable dt = new DataTable();

 

    XmlDocument xmlDoc = new XmlDocument();

    XmlNode rootnode = (XmlNode)xmlDoc.CreateElement("extractedNodes");

 

    foreach (XmlNode node in nl)

    {

        XmlElement xe = xmlDoc.CreateElement(node.Name);             

 

        XmlNodeList subNodeList = node.ChildNodes;

 

        foreach (XmlNode subNode in subNodeList)

        {

            XmlElement se = xmlDoc.CreateElement (subNode.Name);

            se.InnerText = subNode.InnerText;

            xe.AppendChild(se);

        }

 

        rootnode.AppendChild(xe);

 

    }

    xmlDoc.AppendChild(rootnode);

 

 

    ds.ReadXml(new StringReader(xmlDoc.OuterXml));

    dgvResult.DataSource = ds.Tables[0];

    dgvResult.Refresh();

}

Dans la cas présent la découverte des cubes nous renvoie :
 
/content/e1b2a89b-084f-44b2-9fba-ac816ca8195c/image007.png
 
 
» Démarrer une discussion
 
Discussion démarée par bouzahme le 28/08/2008 à 17:15, 1 commentaire(s).