Templates XML

Pour les fichiers XML, il est possible de définir des templates réutilisables. Ces templates sont chargés dans l’ordre suivant:

  • Config/.../<nomFichier>_templates.xml (par exemple TasksAndFields_CGE_templates.xml)
  • Config/.../<nomFichierSansChaine>_templates.xml (par exemple TasksAndFields_templates.xml)
  • Config/Global_templates.xml

Structure

Le noeud principal d’un fichier de template est toujours <Templates> avec un ou plusieurs enfants <Template>.

<Templates>
  <Template ID="tpl1">...</Template>
  <Template ID="tpl2">...</Template>
</Templates>

Un noeud Template se compose en deux parties:

  • <Variables>: conteneur optionnel servant à définir une ou plusieurs varaibles qui devront être précisées lors de l’utilisation du template.
  • <Content>: conteneur avec un unique noeud enfant qui sera injecté à la place de la référence.

Une variable est simplement définie avec un identifiant. Elle peut ensuite être utilisée dans n’importe quel attribut avec ${<idVariable>} et sera remplacée par la valeur définie lors du merge:

<Templates>
  <Template ID="CGE30">
    <Variables>
      <Variable ID="taskId" />
    </Variables>
    <Content>
      ...
    </Content>
  </Template>
</Templates>

Une variable permet de spécifer également 2 attributes:

  • DefaultValue: une valeur par défaut, ainsi le paramétreur n’est pas obligé de spécifier sa valeur lorsque le template est utilisé.
  • DeleteAfterMerge: spécifie si la variable doit être supprimée des attributs du noeud une fois le merge effectué (true par défaut). Cela permet d’utiliser comme variable des attributs qui doivent rester sur le noeud après le merge.

Un template se référence simplement avec l’attribut MergeFrom:

<Task MergeFrom="CGE30" />

A noter que si un template contient une chaîne sous la forme ${xyz}, le moteur va le considérer comme variable non déclarée et renvoyer une erreur. Dans le cas ou ce genre de chaîne doit être ignorée, il faut explicitement l’échapper: \${xyz}.

Exemple

Définition du template:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Templates>
  <Template ID="CGE30">
    <Variables>
      <Variable ID="taskId" />
    </Variables>
    <Content>
      <Task ID="${taskId}" InternLabel="Saisie des écritures" Type="F" TableID="CGEJSA" CallOnPrepareNewEntry="true" NavigatorGridView="${taskId}_N1" NavigatorFilter="${taskId}_NAVFILTER" SubNavigatorTableID="CGEJSA" SubNavigatorGridView="${taskId}_N2" SubNavigatorFilter="${taskId}_SUBNAVFILTER" SubNavigatorAutoSelectFirst="true" CanCloseWithoutTerminate="false">
        <DataField ID="${taskId}_MONTANT_TOTAL" InternLabel="Montant total pour contrôle" Source="TaskOnly" Format="Float" />
        <DataField ID="${taskId}_MONTANT_SAISI" InternLabel="Montant saisi par l'utilisateur en contre-partie" Source="TaskOnly" Format="Float" />
        <DataField ID="${taskId}_HEADER_FINA_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_HEADER_CHAN_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_HEADER_ANAL_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_CPFINA_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_CPCHAN_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_CPANAL_SOLDE" InternLabel="Solde" Source="TaskOnly" Format="Financial" />
        <DataField ID="${taskId}_LAST_PIECE_NUM" InternLabel="Dernier numéro de pièce" Source="TaskOnly" Format="Integer" />
        <DataField ID="${taskId}_CODECR_CONTROL" InternLabel="Déb/créd. contrôle" Source="TaskOnly" Format="Enum" EnumName="DEBIT_CREDIT_COMBO" MaxLength="1" Presentation="RadioButton" />
        <Panel ID="1" InternLabel="En-tête">
          <Group ID="1" InternLabel="Contre-partie 1" Row="1" Column="1" Width="130" Height="11" Icon="">
            <Field ID="NO_SAISIE" InternLabel="No de saisie" DataFieldID="CGEJSA.NOSAIS_PK" Row="-99" LabelColumn="1" Column="0" Width="0" Height="1" LabelVisible="false" Visible="false" />
            <Field ID="CHASOU" InternLabel="Chaîne" DataFieldID="CGEJSA.CHASOU" Row="-99" LabelColumn="0" Column="1" Width="0" Height="1" LabelVisible="false" Visible="false" DefaultValue="CGE" />
              <Couple Key="CGEJSA.NOFINA" ForeignKey="CGECFI.NOCPTE_PK" GridView="CGE02_N1" Filter="${taskId}_SELECT_ACCOUNT_FILTER_FIN" Fusion="true">
              <Field ID="COMPTE_FINANCIER" InternLabel="Compte" DataFieldID="CGEJSA.NOFINA" Row="1" LabelColumn="1" Column="18" Width="15" Height="1" CallOnValidate="true" />
              <Field ID="NOM_COMPTE_FINANCIER" InternLabel="Nom du compte" DataFieldID="CGECFI.NOMCPT" Row="1" LabelColumn="0" Column="35" Width="27" Height="1" LabelVisible="false" CallOnValidate="true" />
              </Couple>
              <Field ID="ECRITURE_PROVISOIRE" InternLabel="Provisoire" DataFieldID="CGEJSA.COVIRT" Row="1" LabelColumn="65" Column="76" Width="20" Height="1" />
              <Field ID="SOLDE_FINANCIER" InternLabel="Solde" DataFieldID="${taskId}_HEADER_FINA_SOLDE" Row="1" LabelColumn="90" Column="95" Width="15" Height="1" Enabled="false" />
              <Couple Key="CGEJSA.NOANAL" ForeignKey="CGECAN.NOCPTE_PK" GridView="CGE03_N1" Filter="${taskId}_SELECT_ACCOUNT_FILTER_ANA" Fusion="true">
              <Field ID="COMPTE_ANALYTIQUE" InternLabel="Compte analytique" DataFieldID="CGEJSA.NOANAL" Row="2" LabelColumn="1" Column="18" Width="15" Height="1" Existence="$CGESOC.COANAL" CallOnValidate="true" />
              <Field ID="NOM_COMPTE_ANALYTIQUE" InternLabel="Nom du compte" DataFieldID="CGECAN.NOMCPT" Row="2" LabelColumn="0" Column="35" Width="27" Height="1" LabelVisible="false" Existence="$CGESOC.COANAL" CallOnValidate="true" />
              </Couple>
            </Group>
        </Panel>
      </Task>
    </Content>
  </Template>
</Templates>

Utilisation dans un fichier:

<Task MergeFrom="CGE30" taskId="CGE30" />

Merging

Lorsque les fichiers du paramétrage sont mergés, le même processing s’applique au niveau des templates. A savoir, il est possible de merger des définitions de templates comme n’importe quelle autre structure XML de paramétrage.

Quand un template est référencé avec MergeFrom, il est également possible de modifier les noeuds enfant en continuant d’utiliser les autres attributs:

<Task MergeFrom="CGE30" taskId="CGE30">
  <DataField ID="CGE30_MONTANT_TOTAL" MergeType="DELETE" />
</Task>
Attention:

Les attributs MergeType, MergeAfter et MergeBefore sont ignorés lors du merging des templates ! Ces attributs ne sont appliqués que lors du merge réel dans les fichiers définitifs. Pour utiliser ces attributs lors du merge des templates, il faut utiliser leur pendants TemplateMergeType, TemplateMergeAfter et TemplateMergeBefore.

Typiquement, si un template doit complètement être écrasé, on utilisera la définition suivante:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Templates>
  <Template ID="MyTemplate" TemplateMergeType="OVERRIDE">
    ...
  </Template>
</Templates>

Référencement interne

Il est possible de référencer un template dans un template:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Templates>
  <Template ID="CGEXE_base">
    <Content>
      <SuperTask ID="CGEXE" InternLabel="Ecritures" Type="X" SuperTaskType="1" TableID="CGEJSA">
        <Child TaskID="CGE30" BtnLabel="Saisie" MainTask="true" Icon="" />
        <Child TaskID="CGE31" BtnLabel="Journal" />
        <Child TaskID="CGEJS" BtnLabel="Vue journal" />
        <Child TaskID="CGEEA" BtnLabel="Vue analyt." />
      </SuperTask>
    </Content>
  </Template>
  <Template ID="CGEXE_rec">
    <Content>
      <SuperTask MergeFrom="CGEXE_base">
        <Child TaskID="CGEEF" BtnLabel="Vue financ." MergeAfter="CGEJS" />
      </SuperTask>
    </Content>
  </Template>
</Templates>

La définition suivante:

<SuperTask MergeFrom="CGEXE_rec" />

donnera le résultat suivant:

<SuperTask ID="CGEXE" InternLabel="Ecritures" Type="X" SuperTaskType="1" TableID="CGEJSA">
  <Child TaskID="CGE30" BtnLabel="Saisie" MainTask="true" Icon="" />
  <Child TaskID="CGE31" BtnLabel="Journal" />
  <Child TaskID="CGEJS" BtnLabel="Vue journal" />
  <Child TaskID="CGEEF" BtnLabel="Vue financ." />
  <Child TaskID="CGEEA" BtnLabel="Vue analyt." />
</SuperTask>

Redéfinition de template

Lorsqu’un template est redéfini dans un module, il est également nécessaire de répéter les noeuds qui y font référence dans le même module.

Dans l’exemple ci-dessous, le module B hérite de A:

<!-- Module A - TasksAndFields_templates.xml -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<Templates>
  <Template ID="tplCGEXE">
    <Content>
      <SuperTask Type="X" SuperTaskType="1" TableID="CGEJSA">
        <Child TaskID="CGE30" BtnLabel="Saisie" MainTask="true" Icon="" />
        <Child TaskID="CGE31" BtnLabel="Journal" />
        <Child TaskID="CGEJS" BtnLabel="Vue journal" />
      </SuperTask>
    </Content>
  </Template>
</Templates>
<!-- Module A - TasksAndFields.xml -->
<SuperTask ID="CGEXE" InternLabel="Ecritures" MergeFrom="tplCGEXE" />
<!-- Module B - TasksAndFields_templates.xml -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<Templates>
  <Template ID="tplCGEXE">
    <Content>
      <SuperTask TemplateMergeType="MERGE_OVERRIDE">
        <Child TaskID="CGEEA" BtnLabel="Vue analyt." />
      </SuperTask>
    </Content>
  </Template>
</Templates>

Afin d’obtenir le bon résultat dans le module B, il est nécessaire d’avoir également:

<!-- Module B - TasksAndFields.xml -->
<SuperTask ID="CGEXE" MergeFrom="tplCGEXE" MergeType="MERGE_OVERRIDE" />

A noter que la tâche CGEXE du mobule B va hériter des attributs définis dans le noeud dans le module A (le InternLabel dans cet exemple).