Product Lifecycle Management -PLM- avec eXtensible Markup Language -XML-



Préambule

L’objet de cette page Web est une approche pragmatique et progressive de eXtensible Markup Language -XML- pour gérer le « contenu » (i.e., les données) d'un système Product Lifecycle Management -PLM-

Les technologies afférentes à XML suivantes sont étudiées : Document Type Definition -DTD-, XML Schema Definition -XSD-, XQuery, eXtensible Style Language Transformations -XSLT-, XML Linking language -XLink-, XPointer et XInclude.

XPath est quant à elle une technologie XML partagée.

Installations

Windows

choco -y upgrade chocolatey (admin.)
choco -y install xsltproc (admin.)
xmllint --version

macOS

brew update
brew upgrade
brew install xmlstarlet
xmllint --version
Sujets
Outillage

Il existe de nombreux outils permettant de « parser » du « code » XML. Le logiciel Apache NetBeans dispose d'un ensemble de fonctionnalités minimal pour construire, contrôler la syntaxe et surtout valider du contenu XML en regard d'un « modèle » (DTD ou XSD). Apache NetBeans permet également l'exécution de programmes XSLT.

A la découverte de Apache NetBeans pour XML

Histoire

L'ancêtre de XML est Standard Generalized Markup Language -SGML-, norme ISO alors que XML est une norme W3C. A ce titre, XML est lu nativement par les browser  Chrome,  Firefox…

Malgré une parenté notoire, HyperText Markup Language -HTML- n'a jamais vraiment eu une filiation parfaite avec XML étant attendu que HTML soit une instanciation de XML. HTML même dans sa version 5 reste permissif (comportement hétérogène des browser  Chrome,  Firefox…) alors que XML ne l'est pas.

eXtensible HyperText Markup Language -XHTML- pensé dans l'esprit XML n'incorpore pas les techno. novatrices de HTML 5 d'où le de facto abandon de ce premier…

Exemple (saut de ligne HTML)

<!-- Saut de ligne HTML : -->
<br>

Exemple (saut de ligne XHTML/XML)

<!-- Saut de ligne XHTML/XML : -->
<br/>

Exemple (saut de ligne XHTML/XML, variante)

<!-- Saut de ligne XHTML/XML : -->
<br>
</br>
Encodage XML

Les balises XML bornent les données à encoder. L'utilisation de caractères spéciaux (escaped characters: <, >, &… ) pour contrôler l'encodage fait appel des stratégies dédiées d'encodage.

<!-- Age Julie < âge Julien & âge Julien > âge Julie -->
<Donnees_problematiques>Age Julie &lt; âge Julien &amp; âge Julien &gt; âge Julie</Donnees_problematiques>

Il est possible d'encoder des caractères HTML moins communs voire des données multimédia comme des sons, images, vidéos….

<!-- 🐉 -->
<Dragon>&#128009;</Dragon>
<Documentation id="FB" name="FB" version="1" notes="FB" infoURI="BarbierDarnal.com"/>
<Icon>
    <Image type="bitmap" xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="bin.base64">Qk12FAEAAAAAADYAAAAoAAAAigAAAKoAAAABABgAAAAAAEAUAQAlFgAAJRYA
            AAAAAAAAAAAALx4hIxgaGxYXGhgYGhUWGBITGRMUGxYXGRQVGBMUFxITFhES
            …
    </Image>
</Icon>

XML autorise du « contenu mixte » où balises s'entrecroisent avec données

<Game_of_Thrones>Les trois <Dragon>&#128009;</Dragon> sont le moyen du pouvoir</Game_of_Thrones>
Expression XML des données (articles)

1ère approche (attributs) PLM_internal_DTD_1.xml 

2e approche (éléments) PLM_external_DTD.xml 

Expression XML des relations entre données (articles et nomenclature de fabrication)

1ère approche (par redondance)

2e approche (par référence des éléments)

3e approche (par référence des valeurs des attributs)

Exercice

A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_internal_DTD_1.xml  avec les liens de nomenclature entre CH005 et P004 ainsi que CH005 et ES000. Compléter avec le poste de charge 600-930 et la gamme de fabrication de CD100

Exercice

A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_external_DTD.xml  avec les liens de nomenclature entre CH005 et P004 ainsi que CH005 et ES000. Compléter avec le poste de charge 600-930 et la gamme de fabrication de CD100

Introduction à Document Type Definition -DTD-

Une DTD décrit un format auquel doit obéir un document XML.

  1. Tutoriel DTD (w3schools)
  2. Tutoriel DTD (Quackit)
  3. Quelques exemples et astuces
  4. Analogie DTD et SQL

DTD externalisée dans un fichier PLM.dtd 

La DTD a été générée dans Apache NetBeans à partir du fichier source XML PLM_external_DTD.xml 

Exercice

A l'aide du logiciel Apache NetBeans, procéder à la validation du fichier source XML PLM_external_DTD.xml 

Référence à la DTD de validation

Conception de Document Type Definition -DTD-

1ère approche (focus sur les attributs)

2e approche (focus sur les éléments)

Exercice

A l'aide du logiciel Apache NetBeans, modifier la partie DTD du fichier PLM_internal_DTD_1.xml  en utilisant IDREFS plutôt que IDREF pour la balise Lien_de_nomenclature. Quel est le risque encouru ? Réponse : besoin d'une convention sur l'ordre des attributs…

Exemple d'utilisation de IDREFS

Exercice

A l'aide du logiciel Apache NetBeans, modifier la partie DTD du fichier PLM_internal_DTD_1.xml  de manière à intégrer la description du poste de charge 600-930 et la gamme de fabrication de CD100

PLM_internal_DTD_1_solution.xml 

Note

La correspondance IDREF/ID est limitée car seul un attribut peut être de type ID. Ainsi, l'intégrité référentielle de Operation vers Poste de charge est empêchée car seul numero_section est de type ID dans Poste de charge. L'utilisation de IDREFS peut être un palliatif.

Exercice

A l'aide du logiciel Apache NetBeans, modifier la partie DTD du fichier PLM_internal_DTD_2.xml  de manière à intégrer la description du poste de charge 600-930 et la gamme de fabrication de CD100

PLM_internal_DTD_2_solution.xml 

Intro. à XML Schema Definition -XSD-

XSD produit un format auquel doit obéir un document XML. XSD est plus puissant que DTD par le typage, la possibilité d'expression de tranformation, le fait que XSD soit écrit en XML lui-même, etc.

  1. Tutoriel XSD (w3schools)
  2. Tutoriel XSD (tutorialspoint)

Exemple Confinement.xsd (modèle)

<?xml version="1.0"?>

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 
    <xs:element name="Confinement" type="xs:date"/>
</xs:schema>

Exemple Confinement.xml (instanciation)

<?xml version="1.0" encoding="UTF-8"?>

<Confinement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Confinement.xsd">
    2020-03-17
</Confinement>

Exercice

A l'aide du logiciel Apache NetBeans, reconsidérer Confinement.xml en représentant les deux confinements français dans le cadre d'une balise racine <Covid_19>…</Covid_19>. Etendre en suivant le fichier Confinement.xsd dans cet esprit…

Solution Covid_19.xsd (modèle)

<?xml version="1.0"?>

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 
    <xs:element name="Covid_19">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Confinement" type="xs:date" minOccurs="2" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Solution Covid_19.xml (instanciation)

<?xml version="1.0" encoding="UTF-8"?>

<Covid_19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Covid_19.xsd">
    <Confinement>2020-03-17</Confinement>
    <Confinement>2020-10-30</Confinement>
</Covid_19>

Un exemple de XSD pour l'Echange de Données Informatisé -EDI- avec EDF

Exercice

A l'aide du logiciel Apache NetBeans, opérer la validation du fichier Debut_Fin.bpmn  au regard de la XSD BPMN20.xsd

xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL https://www.omg.org/spec/BPMN/20100501/BPMN20.xsd"
Intégrité des données avec XSD

XSD autorise la gestion des contraintes d'intégrité référentielle de façon plus poussée que DTD.

  1. Clés primaires, étrangères et unicités
  2. xsd:key

1ère approche (focus sur les attributs) PLM_1.xsd  PLM_with_XSD_1_.xml 

<?xml version="1.0"?>
<!-- Espace de nom 'xs' doit être utilisé dans la déf. du schéma : -->
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 
           
    <!-- Type déporté pour élément 'Lien_de_nomenclature' : -->
    <xs:complexType name="Type_lien_de_nomenclature">
        <!-- Note that attributes have no order : -->
        <!-- DTD-like : -->
        <!-- <xs:attribute name="compose" type="xs:IDREF" use="required"/> -->
        <!-- <xs:attribute name="composant" type="xs:IDREF" use="required"/> -->
        <xs:attribute name="compose" type="xs:string" use="required"/>
        <xs:attribute name="composant" type="xs:string" use="required"/>
        <!-- Attention, certaines quantités de composition sont décimales ! => "xs:decimal" : -->
        <xs:attribute name="quantite_de_composition" type="xs:decimal" use="required"/>
    </xs:complexType> 
    
    <xs:element name="PLM">
        <xs:complexType>
            <!-- 'xs:all' si pas d'ordre -->
            <xs:sequence>
                <!-- Au moins 1 voire plusieurs (1-N) '<Article ... />' ('minOccurs="1"' par défaut) : -->
                <xs:element name="Article" minOccurs="1" maxOccurs="unbounded">
                    <!-- Type *NON* déporté : -->
                    <xs:complexType>
                        <!-- DTD-like ('xs:ID' signifie "primary key") : -->
                        <!-- <xs:attribute name="reference" type="xs:ID" use="required"/> --> 
                        <xs:attribute name="reference" type="xs:string" use="required"/> 
                        <!-- 'default' => 'use="required"' : -->
                        <xs:attribute name="designation" type="xs:string" default="désignation non définie"/> 
                        <xs:attribute name="type_fabrication_achat" type="xs:string" use="required"/> 
                        <xs:attribute name="unite_achat_stock" type="xs:string" use="required"/> 
                        <xs:attribute name="delai_en_semaine" use="required"> 
                            <xs:simpleType> <!-- Attention, nécessaire pour encapsuler une restriction -->
                                <!-- "xs:positiveInteger" => "strictement positif", i.e., "> 0" : -->
                                <xs:restriction base="xs:positiveInteger">
                                    <xs:minInclusive value="1"/>
                                    <xs:maxInclusive value="6"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:attribute>
                        <!-- "optionel" par défaut : -->
                        <xs:attribute name="prix_standard" type="xs:decimal"/> 
                        <xs:attribute name="lot_de_reapprovisionnement" type="xs:positiveInteger"/> 
                        <xs:attribute name="stock_mini" type="xs:positiveInteger"/> 
                        <xs:attribute name="stock_maxi" type="xs:positiveInteger"/> 
                        <xs:attribute name="pourcentage_de_perte" type="xs:unsignedLong"/> 
                        <xs:attribute name="inventaire" type="xs:positiveInteger"/> 
                        <xs:attribute name="PF_ou_MP_ou_Piece_ou_SE" use="required"> 
                            <xs:simpleType>
                                <!-- 'xs:token' data type also contains characters, but the XML processor will remove line feeds, etc. : -->
                                <xs:restriction base="xs:token">
                                    <xs:enumeration value="PF"/>
                                    <xs:enumeration value="MP"/>
                                    <xs:enumeration value="Pi"/>
                                    <xs:enumeration value="SE"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:attribute>
                    </xs:complexType> <!-- Article -->
                </xs:element> <!-- Article -->
                <xs:element name="Lien_de_nomenclature" type="Type_lien_de_nomenclature" maxOccurs="unbounded"/>
                <xs:element name="Poste_de_charge" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence> <!-- Eléments de PLM -->
            <!-- Il semblerait que les attributs de 'PLM' doivent être décrits *APRèS* ses éléments : -->
            <xs:attribute name="author" type="xs:string" fixed="Franck Barbier"/> 
            <xs:attribute name="URL" type="xs:anyURI" fixed="https://franckbarbier.com/Enterprise_Architect/PLM/PLM.html"/> 
        </xs:complexType> <!-- PLM -->

        <!-- Contraintes d'intégrité référentielle -->
        <xs:key name="Article_pk">
            <!-- Chemin relatif de 'Article' dans 'PLM' : -->
            <xs:selector xpath="Article"/>
            <!-- "@" sélectionne un attribut : -->
            <xs:field xpath="@reference"/>
        </xs:key>
        
        <xs:unique name="Article_unique">
            <!-- Chemin relatif de 'Article' dans 'PLM' : -->
            <xs:selector xpath="./Article"/>
            <xs:field xpath="@designation"/>
        </xs:unique>
        
        <xs:key name="Lien_de_nomenclature_pk">
            <xs:selector xpath="Lien_de_nomenclature"/>
            <!-- Clef composée non supportée par DTD : -->
            <xs:field xpath="@compose"/>
            <xs:field xpath="@composant"/>
        </xs:key>
        
        <xs:keyref name="Lien_de_nomenclature_fk_1" refer="Article_pk">
            <!--https://www.tutorialspoint.com/xpath/xpath_expression.htm-->
            <xs:selector xpath="./Lien_de_nomenclature"/>
            <xs:field xpath="@compose"/>
        </xs:keyref>
        
        <xs:keyref name="Lien_de_nomenclature_fk_2" refer="Article_pk">
            <!--https://www.tutorialspoint.com/xpath/xpath_expression.htm-->
            <xs:selector xpath="./Lien_de_nomenclature"/>
            <xs:field xpath="@composant"/>
        </xs:keyref>
        <!-- Fin des contraintes d'intégrité référentielle -->
    </xs:element> <!-- PLM -->
</xs:schema>

Exercice

Opérer la validation dans Apache NetBeans

Exercice

A l'aide du logiciel Apache NetBeans, étendre le fichier PLM_1.xsd  de manière à pouvoir ensuite décrire le poste de charge 600-930 et la gamme de fabrication de CD100 dans le fichier PLM_with_XSD_1_.xml 

2e approche (focus sur les éléments) PLM_2.xsd  PLM_with_XSD_2.xml 

<?xml version="1.0"?>
<!-- Espace de nom 'xsd' doit être utilisé dans la déf. du schéma ! -->
<!-- Default name space: 'xmlns:BDi="https://barbierdarnal.com"' -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
            targetNamespace="https://barbierdarnal.com" xmlns:BDi="https://barbierdarnal.com" version="1.0">
    
    <!-- Type déporté pour élément 'Article' : -->
    <xsd:complexType name="Type_article">
        <xsd:sequence>
            <xsd:element name="designation" type="xsd:string" default="désignation non définie"/> 
            <xsd:element name="type_fabrication_achat" type="xsd:string"/> 
            <xsd:element name="unite_achat_stock" type="xsd:string"/> 
            <xsd:element name="delai_en_semaine"> 
                <xsd:simpleType> 
                    <xsd:restriction base="xsd:positiveInteger">
                        <xsd:minInclusive value="1"/>
                        <xsd:maxInclusive value="6"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:element>
            <!-- "optionel" ('maxOccurs="1"' par défaut) : -->
            <xsd:element name="prix_standard" type="xsd:decimal" minOccurs="0"/> 
            <xsd:element name="lot_de_reapprovisionnement" type="xsd:positiveInteger" minOccurs="0"/> 
            <xsd:element name="stock_mini" type="xsd:positiveInteger" minOccurs="0"/> 
            <xsd:element name="stock_maxi" type="xsd:positiveInteger" minOccurs="0"/> 
            <xsd:element name="pourcentage_de_perte" type="xsd:unsignedLong" minOccurs="0"/> 
            <xsd:element name="inventaire" type="xsd:positiveInteger" minOccurs="0"/> 
            <xsd:element name="PF_ou_MP_ou_Piece_ou_SE"> 
                <xsd:complexType>
                    <xsd:choice>
                        <xsd:element name="PF" type="xsd:string"/>
                        <xsd:element name="MP" type="xsd:string"/>
                        <xsd:element name="Pi" type="xsd:string"/>
                        <xsd:element name="SE" type="xsd:string"/>
                    </xsd:choice>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
        <xsd:attribute name="reference" type="xsd:string" use="required"/>
        <xsd:attribute name="author" default="Franck Barbier" type="xsd:string"/>
    </xsd:complexType> 

    <!-- Type déporté pour élément 'Lien_de_nomenclature' : -->
    <xsd:complexType name="Type_lien_de_nomenclature">
        <xsd:sequence>
            <xsd:element name="compose" type="xsd:string"/>
            <xsd:element name="composant" type="xsd:string"/>
            <xsd:element name="quantite_de_composition" type="xsd:decimal"/>
        </xsd:sequence>
    </xsd:complexType> 
    
    <xsd:element name="PLM">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Article" type="BDi:Type_article" maxOccurs="unbounded"/>
                <xsd:element name="Lien_de_nomenclature" type="BDi:Type_lien_de_nomenclature" maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="author" type="xsd:string" fixed="Franck Barbier"/> 
            <xsd:attribute name="URL" type="xsd:anyURI" fixed="https://franckbarbier.com/Enterprise_Architect/PLM/PLM.html"/> 
            <xsd:attribute name="version" type="xsd:string" fixed="1.0"/>
        </xsd:complexType>

        <!-- Contraintes d'intégrité référentielle -->
        <xsd:key name="Article_pk">
            <xsd:selector xpath="BDi:Article"/>
            <!-- Le champ est relatif dans le scope, i.e., attribut de 'BDi:Article' : -->
            <xsd:field xpath="@reference"/>
        </xsd:key>
        
        <xsd:unique name="Article_unique">
            <xsd:selector xpath="./BDi:Article"/>
            <xsd:field xpath="BDi:designation"/>
        </xsd:unique>
        
        <xsd:key name="Lien_de_nomenclature_pk">
            <xsd:selector xpath="BDi:Lien_de_nomenclature"/>
            <xsd:field xpath="BDi:compose"/>
            <xsd:field xpath="BDi:composant"/>
        </xsd:key>
        
        <xsd:keyref name="Lien_de_nomenclature_fk_1" refer="BDi:Article_pk">
            <xsd:selector xpath="./BDi:Lien_de_nomenclature"/>
            <xsd:field xpath="BDi:compose"/>
        </xsd:keyref>
        
        <xsd:keyref name="Lien_de_nomenclature_fk_2" refer="BDi:Article_pk">
            <xsd:selector xpath="./BDi:Lien_de_nomenclature"/>
            <xsd:field xpath="BDi:composant"/>
        </xsd:keyref>
        <!-- Fin des contraintes d'intégrité référentielle -->
    </xsd:element> 
</xsd:schema>

Exercice

Opérer la validation dans Apache NetBeans

Exercice

A l'aide du logiciel Apache NetBeans, étendre le fichier PLM_2.xsd  de manière à pouvoir ensuite décrire le poste de charge 600-930 et la gamme de fabrication de CD100 dans le fichier PLM_with_XSD_2.xml 

Solution Exercice_PLM.xsd  Exercice_PLM.xml 

Exercice

A l'aide du logiciel Apache NetBeans, revoir le fichier PLM_2.xsd  en créant le type MP à partir du type (pré-existant) Article : reconsidérer l'élément PF_ou_MP_ou_Piece_ou_SE et utilser la balise complexContent. Que peut-on faire alors de l'élément pourcentage_de_perte ?

Exercice

Soit le fichier de données de détenus et de décisions prises à leur égard (Condamnation-1, Réduction de peine-2, Libération définitive-3). Si on enlève les commentaires des lignes 18 à 23, on veut que la validation échoue, à savoir « une décision de même type (1, 2 ou 3) ne peut pas être prise pour le même détenu le même jour ». Modifier le fichier Prison.xsd en conséquence…

<?xml version="1.0"?>
<Prison xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Prison.xsd">
    <Detenu>
        <n_ecrou>111111</n_ecrou>
        <prenom>Belzébuth</prenom>
    </Detenu>
    <Detenu>
        <n_ecrou>999999</n_ecrou>
        <prenom>Lucifer</prenom>
    </Detenu>
    <Condamnation>
        <n_type_decision>1</n_type_decision>
        <n_ecrou>111111</n_ecrou>
        <date_decision>2020-10-30</date_decision>
        <duree>10</duree>
    </Condamnation>
    <!-- Duplicate key value [1,111111,2020-10-30] declared for identity constraint "Condamnation_key" of element "Prison" : -->
    <!--<Condamnation>-->
    <!--<n_type_decision>1</n_type_decision>-->
    <!--<n_ecrou>111111</n_ecrou>-->
    <!--<date_decision>2020-10-30</date_decision>-->
    <!--<duree>20</duree>-->
    <!--</Condamnation>-->
    <Condamnation>
        <n_type_decision>1</n_type_decision>
        <n_ecrou>999999</n_ecrou>
        <date_decision>2020-10-30</date_decision>
        <duree>20</duree>
    </Condamnation>
    <Reduction_peine>
        <n_type_decision>2</n_type_decision>
        <n_ecrou>111111</n_ecrou>
        <date_decision>2020-10-30</date_decision>
        <duree>5</duree>
    </Reduction_peine>
    <Liberation_definitive>
        <n_type_decision>3</n_type_decision>
        <n_ecrou>111111</n_ecrou>
        <date_decision>2020-10-30</date_decision>
        <date_liberation>2021-01-04</date_liberation>
    </Liberation_definitive>
</Prison>

Fichier Prison.xsd

<?xml version="1.0"?> <!-- Prison.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.0"> 
    <xsd:complexType name="Detenu_type">
        <xsd:sequence>
            <xsd:element name="n_ecrou" type="xsd:string" minOccurs="1" maxOccurs="1"/> 
            <xsd:element name="prenom" type="xsd:string"/> 
        </xsd:sequence>
    </xsd:complexType> 

    <xsd:complexType name="Decision_type">
        <xsd:sequence>
            <xsd:element name="n_type_decision"> 
                <xsd:simpleType> 
                    <xsd:restriction base="xsd:positiveInteger">
                        <xsd:minInclusive value="1"/>
                        <xsd:maxInclusive value="3"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:element>
            <xsd:element name="n_ecrou" type="xsd:string"/> 
            <xsd:element name="date_decision" type="xsd:date"/>
            <xsd:element name="duree" type="xsd:positiveInteger" minOccurs="0" maxOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType> 
    
    <xsd:complexType name="Condamnation_type">
        <xsd:complexContent>
            <xsd:restriction base="Decision_type">
                <xsd:sequence>
                    <xsd:element name="n_type_decision"> 
                        <xsd:simpleType> 
                            <xsd:restriction base="xsd:positiveInteger">
                                <xsd:minInclusive value="1"/>
                                <xsd:maxInclusive value="1"/>
                            </xsd:restriction>
                        </xsd:simpleType>
                    </xsd:element>
                    <xsd:element name="n_ecrou" type="xsd:string"/> 
                    <xsd:element name="date_decision" type="xsd:date"/>
                    <xsd:element name="duree" type="xsd:positiveInteger" minOccurs="1" maxOccurs="1"/>
                </xsd:sequence>
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:complexType name="Reduction_peine_type">
        <xsd:complexContent>
            <xsd:restriction base="Decision_type">
                <xsd:sequence>
                    <xsd:element name="n_type_decision"> 
                        <xsd:simpleType> 
                            <xsd:restriction base="xsd:positiveInteger">
                                <xsd:minInclusive value="2"/>
                                <xsd:maxInclusive value="2"/>
                            </xsd:restriction>
                        </xsd:simpleType>
                    </xsd:element>
                    <xsd:element name="n_ecrou" type="xsd:string"/> 
                    <xsd:element name="date_decision" type="xsd:date"/>
                    <xsd:element name="duree" type="xsd:positiveInteger" minOccurs="1" maxOccurs="1"/>
                </xsd:sequence>
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:complexType name="Liberation_definitive_type">
        <xsd:complexContent>
            <xsd:restriction base="Decision_type">
                <xsd:sequence>
                    <xsd:element name="n_type_decision"> 
                        <xsd:simpleType> 
                            <xsd:restriction base="xsd:positiveInteger">
                                <xsd:minInclusive value="3"/>
                                <xsd:maxInclusive value="3"/>
                            </xsd:restriction>
                        </xsd:simpleType>
                    </xsd:element>
                    <xsd:element name="n_ecrou" type="xsd:string"/> 
                    <xsd:element name="date_decision" type="xsd:date"/>
                    <xsd:element name="date_liberation" type="xsd:date"/>
                </xsd:sequence>
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:element name="Prison">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Detenu" type="Detenu_type" maxOccurs="unbounded"/>
                <xsd:element name="Condamnation" type="Condamnation_type" maxOccurs="unbounded"/>
                <xsd:element name="Reduction_peine" type="Reduction_peine_type" maxOccurs="unbounded"/>
                <xsd:element name="Liberation_definitive" type="Liberation_definitive_type" maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="author" default="Franck Barbier" type="xsd:string"/>
            <xsd:attribute name="URL" default="https://BarbierDarnal.com/Enterprise_Architect/Prison_de_Nantes/Prison_de_Nantes.html" type="xsd:anyURI"/>
            <xsd:attribute name="version" type="xsd:string" fixed="1.1"/>
        </xsd:complexType>

        <xsd:key name="Detenu_key">
            <xsd:selector xpath="./Detenu"/>
            <xsd:field xpath="./n_ecrou"/>
        </xsd:key>
        
        <xsd:key name="Condamnation_key">
            <!-- ? -->
        </xsd:key>
        <xsd:keyref name="Condamnation_fk" refer="Detenu_key">
            <xsd:selector xpath="Condamnation"/>
            <xsd:field xpath="n_ecrou"/>
        </xsd:keyref>
        
        <xsd:key name="Reduction_peine_key">
            <!-- ? -->
        </xsd:key>
        <xsd:keyref name="Reduction_peine_fk" refer="Detenu_key">
            <xsd:selector xpath="Reduction_peine"/>
            <xsd:field xpath="n_ecrou"/>
        </xsd:keyref>
        
        <xsd:key name="Liberation_definitive_key">
            <!-- ? -->
        </xsd:key>
        <xsd:keyref name="Liberation_definitive_fk" refer="Detenu_key">
            <xsd:selector xpath="Liberation_definitive"/>
            <xsd:field xpath="n_ecrou"/>
        </xsd:keyref>
    </xsd:element> 
</xsd:schema>
Espace de nommage

Les espaces de nommage permettent d'organiser la sépcification des données et en corollaire de gérer les conflits de nommage dès lors que les données proviennent de sources différentes.

Exemple FB.xsd  FB.xml 

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="FranckBarbier">
    <!-- 'xsd:annotation' a pour principe d'expliquer la nature et la finalité de la XSD -->
    <xsd:annotation>
        <xsd:appinfo>Intro. à la notion d'espace de nommage...</xsd:appinfo>
        <xsd:documentation xml:lang="fr">
            La balise 'SALUTATION' appartient à l'espace de nommage 'FranckBarbier'
        </xsd:documentation>
    </xsd:annotation>
    <xsd:element name="SALUTATION" type="xsd:string"/>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!-- L'espace de nommage 'FB' est introduit en référence à l'espace de nommage 'FranckBarbier' -->
<FB:SALUTATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:FB="FranckBarbier"
               xsi:schemaLocation="FranckBarbier FB.xsd">Bonjour !</FB:SALUTATION>

targetNamespace

L'absence de targetNamespace simplifie les choses.

Exemple FB_.xsd  FB_.xml 

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="SALUTATION" type="xsd:string"/>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<SALUTATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="FB_.xsd">Bonjour !</SALUTATION>

elementFormDefault="qualified"

L'attribut elementFormDefault de la balise schema est par défaut fixé à la valeur "unqualified".

Exemple A.xsd  A.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!-- https://stackoverflow.com/questions/1463138/what-does-elementformdefault-do-in-xsd -->
<!-- If 'elementFormDefault="qualified"' is absent
then the default unqualified value means that *locally declared elements, e.g., 'assignment' are in no namespace* -->
<!-- Test 'A.xml' and next add 'elementFormDefault="qualified"' -->
<!-- Les espaces de nommage 'COUCOU' et 'BDi' sont introduits et utilisés -->
<COUCOU:schema xmlns:COUCOU="http://www.w3.org/2001/XMLSchema"
               xmlns:BDi="https://barbierdarnal.com"
               targetNamespace="https://barbierdarnal.com">
    <COUCOU:element name="assignments">
        <COUCOU:complexType>
            <COUCOU:sequence>
                <COUCOU:element name="assignment" type="BDi:assignment_data" minOccurs="1" maxOccurs="unbounded"/>
            </COUCOU:sequence>
        </COUCOU:complexType>
    </COUCOU:element>
    <COUCOU:complexType name="assignment_data">
        <COUCOU:sequence>
            <COUCOU:element name="name" type="COUCOU:string"/>
        </COUCOU:sequence>
        <COUCOU:attribute name="what" type="COUCOU:string" use="required"/>
    </COUCOU:complexType>
</COUCOU:schema>
<?xml version="1.0" encoding="UTF-8"?>
<assignments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="https://barbierdarnal.com"
             xsi:schemaLocation="https://barbierdarnal.com A.xsd">
    <!-- 'assignment' n'est pas dans un espace de nommage -->
    <!-- Supprimer 'xmlns=""' si 'elementFormDefault="qualified"' dans XSD -->
    <assignment what="formation XML" xmlns="">
        <name>Franck Barbier</name>
    </assignment>
</assignments>

Modularité ⤳ import

L'idée et l'intérêt sont de segmenter la définiion de la XSD en plusieurs fichiers résultant probablement d'analyses antérieures et/ou séparées.

Exemple Voyageurs.xsd  Voyageur.xsd  Adresses.xsd  Voyageurs.xml 

<?xml version="1.0" encoding="utf-16"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="https://BarbierDarnal.com"
        xmlns:V="V"
        attributeFormDefault="qualified" elementFormDefault="qualified">
    <import schemaLocation="Voyageur.xsd" namespace="V"/>
    <element name="Voyageurs">
        <complexType>
            <sequence>
                <element name="Voyageur" type="V:Voyageur_type"/>
            </sequence>
        </complexType>
    </element>
</schema>
<?xml version="1.0" encoding="utf-16"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="V"
        xmlns:A="A"
        attributeFormDefault="qualified" elementFormDefault="qualified">
    <import schemaLocation="Adresses.xsd" namespace="A"/>
    <complexType name="Voyageur_type">
        <sequence>
            <element name="Nom" type="string"/>
            <element name="Residence_FR" type="A:FR_adresse_type" minOccurs="0"/>
            <element name="Residence_US" type="A:US_adresse_type" minOccurs="0"/>
        </sequence>
    </complexType>
</schema>
<?xml version="1.0" encoding="UTF-16"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="A"
        attributeFormDefault="qualified" elementFormDefault="qualified">
    <!-- 'FR_adresse_type' et 'US_adresse_type' appartiennent a l'espace de nommmage 'A' -->
    <complexType name="FR_adresse_type">
        <sequence>
            <element name="Numero_rue" type="string"/>
            <element name="Rue" type="string"/>
            <element name="Code_postal" type="positiveInteger"/>
            <element name="Ville" type="string"/>
        </sequence>
    </complexType>
    <complexType name="US_adresse_type">
        <attribute name="street_number" type="string" use="required"/> 
        <attribute name="street" type="string" use="required"/> 
        <attribute name="zip_code" type="positiveInteger" use="required"/>
        <attribute name="city" type="string" use="required"/>
        <attribute name="state" use="required">
            <simpleType>
                <restriction base="token">
                    <enumeration value="Alabama"/>
                    <enumeration value="Nevada"/>
                    <enumeration value="South Dakota"/>
                    <enumeration value="Texas"/>
                    <!-- Etc. -->
                </restriction>
            </simpleType>
        </attribute>
    </complexType>
</schema>
<?xml version="1.0" encoding="utf-16"?>
<BDi:Voyageurs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="https://BarbierDarnal.com Voyageurs.xsd"
               xmlns:BDi="https://BarbierDarnal.com"
               xmlns:V="V"
               xmlns:A="A">
    <BDi:Voyageur>
        <V:Nom>Franck Barbier</V:Nom>
        <V:Residence_FR>
            <A:Numero_rue>3</A:Numero_rue>
            <A:Rue>Alexander Taylor</A:Rue>
            <A:Code_postal>64000</A:Code_postal>
            <A:Ville>Pau</A:Ville>
        </V:Residence_FR>  
    </BDi:Voyageur>
</BDi:Voyageurs>

Exercice

A l'aide du logiciel Apache NetBeans, créer un fichier Moyen_transport.xsd décrivant le type Moyen_transport_type (valeurs possibles : Avion et Bateau) dans l'espace de nommage M. Amender le fichier Voyageur.xsd pour spécifier qu'une donnée de type Voyageur_type possède un élément unique de type Moyen_transport_type. Finalement, modifier le fichier Voyageurs.xml de sorte qu'il n'y ait pas d'erreur à la validation.

Solution

<?xml version="1.0" encoding="utf-16"?>
<BDi:Voyageurs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="https://BarbierDarnal.com Voyageurs.xsd"
               xmlns:BDi="https://BarbierDarnal.com"
               xmlns:V="V"
               xmlns:A="A">
    <BDi:Voyageur>
        <V:Nom>Franck Barbier</V:Nom>
        <V:Residence_FR>
            <A:Numero_rue>3</A:Numero_rue>
            <A:Rue>Alexander Taylor</A:Rue>
            <A:Code_postal>64000</A:Code_postal>
            <A:Ville>Pau</A:Ville>
        </V:Residence_FR>  
        <V:Moyen_de_transport>Avion</V:Moyen_de_transport>
    </BDi:Voyageur>
</BDi:Voyageurs>
<?xml version="1.0" encoding="utf-16"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="V"
        xmlns:A="A"
        xmlns:M="M"
        attributeFormDefault="qualified" elementFormDefault="qualified">
    <import schemaLocation="Adresses.xsd" namespace="A"/>
    <import schemaLocation="Moyen_de_transport.xsd" namespace="M"/>
    <complexType name="Voyageur_type">
        <sequence>
            <element name="Nom" type="string"/>
            <element name="Residence_FR" type="A:FR_adresse_type" minOccurs="0"/>
            <element name="Residence_US" type="A:US_adresse_type" minOccurs="0"/>
            <element name="Moyen_de_transport" type="M:Moyen_transport_type"/>
        </sequence>
    </complexType>
</schema>
<?xml version="1.0" encoding="utf-16"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="M"
        attributeFormDefault="qualified" elementFormDefault="qualified">
    <simpleType name="Moyen_transport_type">
        <restriction base="string">
            <enumeration value="Avion"/>
            <enumeration value="Bateau"/>
        </restriction>
    </simpleType>
</schema>

Modularité ⤳ ref

L'idée et l'intérêt sont de réutiliser des spécifications de type « élémentaire » dans d'autres types plus « complexes ».

Exemple

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xsd:element name="Dish_option" type="xsd:string"/>
    <xsd:element name="Dessert" substitutionGroup="Dish_option"/>
    <xsd:element name="Starter" substitutionGroup="Dish_option"/>
    <xsd:element name="Dish">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Starter" minOccurs="0"/>
                <xsd:element name="Main_course" type="xsd:string"/>
                <xsd:element ref="Dessert" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<Dish xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Dish.xsd">
    <Main_course>Hamburger</Main_course>
    <Dessert>Tiramisu</Dessert>
</Dish>

Modularité ⤳ include

Exercice

A l'aide du logiciel Apache NetBeans, télécharger le fichier Dish.xsd  puis créer un fichier Day.xsd et, en utilisant include, décrire l'élément Day comme une suite de trois Dish à savoir Breakfast, Lunch puis Dinner.

Exemple Dish.xsd  Dish.xml 

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="D"
            elementFormDefault="qualified"
            xmlns:Dish_name_space="D">
    <xsd:element name="Dish_option" type="xsd:string"/>
    <xsd:element name="Dessert" substitutionGroup="Dish_name_space:Dish_option"/>
    <xsd:element name="Starter" substitutionGroup="Dish_name_space:Dish_option"/>
    <xsd:element name="Dish">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Dish_name_space:Starter" minOccurs="0"/>
                <xsd:element name="Main_course" type="xsd:string"/>
                <xsd:element ref="Dish_name_space:Dessert" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<Dish:Dish xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="D Dish.xsd"
           xmlns:Dish="D">
    <Dish:Main_course>Hamburger</Dish:Main_course>
    <Dish:Dessert>Tiramisu</Dish:Dessert>
</Dish:Dish>

Solution Day.xsd  Day.xml 

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="D"
            elementFormDefault="qualified"
            xmlns:Day_name_space="D">
    <!-- https://stackoverflow.com/questions/2357943/whats-the-difference-between-xsdinclude-and-xsdimport -->
    <!-- L'espace de nommage 'D' de 'Dish.xsd' doit être maintenu via 'include' -->
    <xsd:include schemaLocation="Dish.xsd"/>
    <xsd:element name="Breakfast" substitutionGroup="Day_name_space:Dish"/>
    <xsd:element name="Lunch" substitutionGroup="Day_name_space:Dish"/>
    <xsd:element name="Dinner" substitutionGroup="Day_name_space:Dish"/>
    <xsd:element name="Day">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Day_name_space:Breakfast" minOccurs="0"/>
                <xsd:element ref="Day_name_space:Lunch"/>
                <xsd:element ref="Day_name_space:Dinner" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
<?xml version="1.0"?>
<Data:Day xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="D Day.xsd"
          xmlns:Data="D">
    <Data:Breakfast>
        <Data:Starter>Orange juice</Data:Starter>
        <Data:Main_course>Coffee</Data:Main_course>
    </Data:Breakfast>
    <Data:Lunch>
        <Data:Main_course>Lasagna</Data:Main_course>
        <Data:Dessert>Banana</Data:Dessert>
    </Data:Lunch>
    <Data:Dinner>
        <Data:Main_course>Soup</Data:Main_course>
    </Data:Dinner>
</Data:Day>
XQuery est à XML ce que Structured Query Language -SQL- est aux bases de données relationnelles

XQuery est un langage de requêtes disposant d'une syntaxe propre et de fonctions pour « interroger » un document XML. Le résultat est un autre document XML qui n'est rien d'autre que le résultat d'une transformation. A ce titre, comme XSLT, XQuery peut produire du HTML, JavaScript Object Notation -JSON-, SQL ou encore YAML Ain't Markup Language -YAML- qui est un sur-ensemble de JSON.

Une comparaison entre JSON et XML est présentée

  1. Tutoriel XQuery (w3schools)
  2. Tutoriel XQuery (tutorialspoint)
  3. (Encore un…) tutoriel XQuery

XQuery utiliseXPath. Accès aux éléments d'un document XML avecXPath :

La nécessité d'un système d'exécution de XQuery (absent de Apache NetBeans) impose l'utilisation d'outils idoines comme Saxon.

Exemple (cf. fichier Articles.xml)

(: The doc() function is used to open the "Articles.xml" file: :)
(: Requête : extraire tous les produits finis... :)
doc("./data/Articles.xml")/Articles/Article[@PF_ou_MP_ou_Piece_ou_SE = 'PF']

Exemple (SQL-compliant)

SELECT * FROM Article WHERE PF_ou_MP_ou_Piece_ou_SE = 'PF';

Exemple (cf. fichier Articles.xml)

(: Requête : extraire la désignation de tous les produits finis... :)
(: La fonction 'data' est obligatoire... :)
doc("./data/Articles.xml")/Articles/Article[@PF_ou_MP_ou_Piece_ou_SE = 'PF']/data(./@designation)

Exemple (SQL-compliant)

SELECT designation FROM Article WHERE PF_ou_MP_ou_Piece_ou_SE = 'PF';

XQuery offre les expressions FLWOR (For Let Where Order Return) pour écrire des requêtes complexes.

Exemple (cf. fichier Articles.xml)

(: Requête : extraire toutes les références des produits finis par ordre alphabétique inverse de leur désignation... :)
for $a in doc("./data/Articles.xml")/Articles/Article
where $a/@PF_ou_MP_ou_Piece_ou_SE = 'PF'
order by $a/@designation descending
(: La fonction 'data' est obligatoire... :)
return data($a/@reference)

Exemple (SQL-compliant)

SELECT reference FROM Article ORDER BY designation DESC WHERE PF_ou_MP_ou_Piece_ou_SE = 'PF'; 

Exercice

Opérer les requêtes dans Apache NetBeans

XQueryXML to HTML

Outre les expressions FLWOR, la structure de contrôle (if () then () else ()) peut (aussi) être utile pour écrire des requêtes ou transformations complexes.

Exemple (fichier source Articles_.xml )

(: Composants (rôle)... :)

(: '//' signifie qu'on balaie tous les éléments '<Article>' quelque soit leur niveau de profondeur :)
let $articles := doc("./data/Articles_.xml")//Article  
let $liens_de_nomenclature := doc("./data/Articles_.xml")//Lien_de_nomenclature

return  <table><tr><th>Réference=</th><th>Désignation</th><th>Type</th></tr>
        {
            for $article in $articles 
            where true()
            return
                <tr>
                {
(: Attention, les composants apparaîtront plusieurs fois, voir la fonction 'distinct-values' :)
                        for $lien_de_nomenclature in $liens_de_nomenclature   
                        return
                            if (data($lien_de_nomenclature/composant) = data($article/@reference))
                            (: Attention à la virgule à l'intérieur du 'then' :)
                            then (  <td>{data($article/@reference)}</td>,
                                    <td>{data($article/designation)}</td>,
(: '*' signifie tous les éléments fils puis on prend le 1er... :)
                                    <td>{name($article/PF_ou_MP_ou_Piece_ou_SE/*[1])}</td>)
                            else ()
                }
                </tr>
        }
</table>

Résultat

Réference Désignation Type
CH005 chassis monte SE CH005 chassis monte SE
ES000 essieu monte SE
ROUE50 roue de camion Pi

Exercice

Opérer les requêtes dans Apache NetBeans

Exercice

Ecrire en fonction du fichier source Articles_.xml  la requête XQuery « Quels sont les composés (référence et désignation) dans lequel entre CH005 comme composant et avec quelle quantité ? ».

Indication (fonction concat)

(: Requête : extraire tous les couples référence/désignation des articles... :)
let $Reference := "Référence : "  
let $Designation := "Désignation : "  
for $a in doc("./data/Articles.xml")/Articles/Article
return concat($Reference,data($a/@reference)," ",$Designation,data($a/@designation))

Solutions

for $lien_de_nomenclature in doc("./data/Articles_.xml")//Lien_de_nomenclature
where $lien_de_nomenclature/composant = "CH005"
return concat($lien_de_nomenclature/compose," en utilise ",$lien_de_nomenclature/quantite_de_composition)
let $filtre := doc("./data/Articles_.xml")//Lien_de_nomenclature[./composant = 'CH005']
for $lien_nomclature in $filtre
return concat($lien_nomclature/compose," en utilise ",$lien_nomclature/quantite_de_composition)
XQueryXML to XML

Comme XSLT, XQuery autorise des transformations de XML vers XML.

  1. Tutoriel XQuery sur la construction d'éléments et d'attributs

Exemple (fichier source data/PLM_source.xml dans le programme Java Saxon)

(: Transformation 'PLM_source_TO_PLM_target.xqy'... :)
<PLM>
{
    (: Better: 'for $article in doc("./data/PLM_source.xml")/*/Article' :)
    for $article in doc("./data/PLM_source.xml")/PLM/Article 
    (: Construction d'un élément (https://www.altova.com/training/xquery3/constructors)... :)
    return element {$article/name()}
    {
        (: Tous les attributes... :)
        for $attribut_de_article in $article/@*
        return 
            (: 'reference' doit rester un attribut contrairement aux autres attributs qui deviennent des éléments :)
            if ($attribut_de_article/name() = "reference")
            then attribute {$attribut_de_article/name()} {data($attribut_de_article)} 
            else
                (: 'PF_ou_MP_ou_Piece_ou_SE' devient un élément avec sous élément :)
                if ($attribut_de_article/name() = "PF_ou_MP_ou_Piece_ou_SE")
                then element {$attribut_de_article/name()}
                {
                    let $attribut_devient_sous_element := data($attribut_de_article)
                    (: Element vide... :)
                    return element {$attribut_devient_sous_element} {}
                }
                else element {$attribut_de_article/name()} {data($attribut_de_article)}
    }
}
</PLM>

Exercice

Opérer la transformation dans Apache NetBeans

Exercice

La transformation XQuery précédente gère l'élément <PLM> ... </PLM> « en dur ». Remplacer cette gestion par la production automatique d'un élément dont le nom est le calcul XQuery du nom de la racine du fichier source XML.

(: Transformation 'PLM_source_TO_PLM_target_.xqy'... :)

element {doc("./data/PLM_source.xml")/*/name()}
{
    …
}

Exercice

Ecrire la transformation inverse de PLM_target.xml  vers PLM_source.xml 

Solution

eXtensible Style Language Transformations -XSLT- ⤳ XML to HTML

XSLT (a.k.a. XSL) est un langage impératif et donc doté de structures de contrôle pour transformer un document XML en un autre. Il est possible d'effectuer d'autres transformations vers CVS, JSON, HTML, LDIF, RTF, SQL, YAML, etc.

XSLT s'appuie foncièrement surXPath pour établir la manière dont tout élément ou ensemble d'éléments XML est transformé vers un « motif » de code cible. Note : XSLT etXQuery tous deux utilisentXPath comme sous-langage.

  1. Tutoriel XSLT (w3schools)
  2. Tutoriel XSLT (MDN)

Exemple PLM_with_XSD_1_.xml 

<?xml version="1.0" encoding="UTF-8"?>
<PLM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PLM_1.xsd">
    <Article reference="CD100"
             designation="camion demenagement bleu"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="PF"/>
    <Article reference="CH005"
             designation="chassis monte"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="SE"/>
    <Article reference="H000"
             designation="conteneur bleu"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="1"
             lot_de_reapprovisionnement="150"
             stock_mini="350"
             stock_maxi="800"
             PF_ou_MP_ou_Piece_ou_SE="SE"/>
    <Lien_de_nomenclature compose="CD100"
                  composant="CH005"
                  quantite_de_composition="1"/>
    <Lien_de_nomenclature compose="CD100"
                  composant="H000"
                  quantite_de_composition="1"/>
</PLM>

Cible HTML

Transformation PLM_with_XSD_1_TO_WEB.xsl 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"/>
    <!-- The '<xsl:template>' element contains rules to apply when a specified node is matched… -->
    <!-- 'match="/"' defines the whole document: -->
    <xsl:template match="/">
        <html>
            <head>
                <title>PLM_with_XSD_1_TO_WEB.xsl</title>
            </head>
            <body>
                <!--<h2>Source: <a href="./PLM_with_XSD_1_.xml">PLM_with_XSD_1_.xml</a>-->
                <!--<br/>Transformation: <a href="./PLM_with_XSD_1_TO_WEB.xsl">PLM_with_XSD_1_TO_WEB.xsl</a>-->
                <!--</h2>-->
                <xsl:variable name="PLM"/>
                <xsl:choose>
                    <xsl:when test="not($PLM)"> <!-- No value at all... -->
                        <h3 style="padding: 10px 10px 10px 10px;">PLM</h3>
                    </xsl:when>
                    <xsl:otherwise>
                        <h3 style="padding: 25px 25px 25px 25px;">
                            <xsl:value-of select="$PLM"/>
                        </h3>
                    </xsl:otherwise>
                </xsl:choose>
                <table border="1">
                    <tr>
                        <th style="background-color: aqua;">
                            <!-- Get the name of the element instead of the element's value -->
                            <xsl:value-of select="local-name(PLM/Article)"/>
                        </th>
                        <th style="background-color: powderblue;">
                            <xsl:value-of select="local-name(PLM/Lien_de_nomenclature/@quantite_de_composition)"/>
                        </th>
                        <th style="background-color: powderblue;">
                            <xsl:value-of select="local-name(PLM/Lien_de_nomenclature/@composant)"/>
                        </th>
                    </tr>
                    <xsl:for-each select="PLM/Article">
                        <!-- Variables in XSLT may only be assigned a value once: -->
                        <xsl:variable name="reference_courante" select="./@reference"/>
                        <!-- Attention chemin relatif car le contexte est 'Article' : -->
                        <xsl:for-each select="../Lien_de_nomenclature"> <!-- Ou alors : '<xsl:for-each select="/PLM/Lien_de_nomenclature">' -->
                            <xsl:choose>
                                <xsl:when test="./@compose = $reference_courante and position() = 1">
                                    <tr>
                                        <td>
                                            <!-- XPath attribute access: -->
                                            <xsl:value-of select="$reference_courante"/> <!-- Ou alors : '<xsl:value-of select="./@reference"/>' -->
                                        </td>
                                        <td style="text-align:center;">
                                            <xsl:value-of select="@quantite_de_composition"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="@composant"/>
                                        </td>
                                    </tr>
                                </xsl:when>
                                <!-- 'not(position() = 1)' as well: -->
                                <xsl:when test="./@compose = $reference_courante and position() != 1">
                                    <tr>
                                        <td></td>
                                        <td style="text-align:center;">
                                            <xsl:value-of select="@quantite_de_composition"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="@composant"/>
                                        </td>
                                    </tr>
                                </xsl:when>
                                <xsl:otherwise> 
                                    <xsl:if test="position() = 1">
                                        <tr>
                                            <td>
                                                <xsl:value-of select="$reference_courante"/>
                                            </td>
                                            <td></td>
                                            <td></td>
                                        </tr>
                                    </xsl:if>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:for-each>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Exercice

Opérer la transformation dans Apache NetBeans

eXtensible Style Language Transformations -XSLT- ⤳ XML to XML

La transformation XML à XML est la plus « requise » dans le cadre de traitement massif de données : extraction, enrichissement, comparaison, fusion…

Exemple PLM_source.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!-- L'ouverture de ce source XML dans un browser compatible XSLT provoque la transformation : -->
<?xml-stylesheet type="text/xsl" href="PLM_source_TO_PLM_target.xsl"?>
<PLM>
    <Article reference="CD100"
             designation="camion demenagement bleu"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="PF"/>
    <Article reference="CH005"
             designation="chassis monte"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="SE"/>
    <!-- ... -->
    <Lien_de_nomenclature compose="CD100"
                  composant="CH005"
                  quantite_de_composition="1"/>
    <!-- ... -->
</PLM>

Cible XML PLM_target.xml 

<?xml version="1.0" encoding="UTF-8"?>
<PLM>
    <Article reference="CD100">
        <designation>camion demenagement bleu</designation>
        <type_fabrication_achat>fabr. par lot</type_fabrication_achat>
        <unite_achat_stock>unite</unite_achat_stock>
        <delai_en_semaine>2</delai_en_semaine>
        <lot_de_reapprovisionnement>200</lot_de_reapprovisionnement>
        <stock_maxi>600</stock_maxi>
        <PF_ou_MP_ou_Piece_ou_SE>
            <PF/>
        </PF_ou_MP_ou_Piece_ou_SE>
    </Article>
    <Article reference="CH005">
        <designation>chassis monte</designation>
        <type_fabrication_achat>fabr. par lot</type_fabrication_achat>
        <unite_achat_stock>unite</unite_achat_stock>
        <delai_en_semaine>1</delai_en_semaine>
        <lot_de_reapprovisionnement>300</lot_de_reapprovisionnement>
        <stock_maxi>900</stock_maxi>
        <PF_ou_MP_ou_Piece_ou_SE>
            <SE/>
        </PF_ou_MP_ou_Piece_ou_SE>
    </Article>
    <!-- ... -->
    <Lien_de_nomenclature>
        <compose>CD100</compose>
        <composant>CH005</composant>
        <quantite_de_composition>1</quantite_de_composition>
    </Lien_de_nomenclature>
    <!-- ... -->
</PLM>

Transformation PLM_source_TO_PLM_target.xsl 

<?xml version="1.0" encoding="UTF-8"?>
<!-- '<xsl:stylesheet>' and '<xsl:transform>' are completely synonymous: -->
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <!-- La cible est du XML : -->
    <xsl:output method="xml" indent="yes"/>
    <!-- The 'match' attribute is used to associate a template with an XML element, say '/' as the root: -->
    <xsl:template match="/PLM">
        <PLM>
            <xsl:apply-templates select="Article"/>
            <xsl:text disable-output-escaping="yes"><!-- ... --></xsl:text> 
            <xsl:apply-templates select="Lien_de_nomenclature"/>
            <xsl:text disable-output-escaping="yes"><!-- ... --></xsl:text> 
        </PLM>
    </xsl:template>
    <xsl:template match="Article">
        <xsl:element name="{local-name()}">
            <!-- Ajout d'un attribut à l'élément : -->
            <xsl:attribute name="reference">
                <xsl:value-of select="@reference"/>
            </xsl:attribute>
            <!--First sub-element:-->
            <!--<designation>-->
            <!--<xsl:value-of select="@designation"/>-->
            <!--</designation>-->
            <!-- Itération sur tous (i.e., '*') les attributs (i.e., '@') : -->
            <xsl:for-each select="@*">
                <!-- Pas terrible... on exclut le 1er attribut, e.g., 'reference' : -->
                <!-- Revoir ce test car les attributs sont par définition non ordonnés : -->
                <xsl:if test="position() != 1">
                    <xsl:element name="{local-name(.)}">
                        <xsl:choose>
                            <xsl:when test="local-name(.) = 'PF_ou_MP_ou_Piece_ou_SE'">
                                <xsl:element name="{.}">
                                </xsl:element>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="."/>
                            </xsl:otherwise>
                        </xsl:choose> 
                    </xsl:element>   
                </xsl:if>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
    <xsl:template match="Lien_de_nomenclature">
        <xsl:element name="{local-name()}">
            <xsl:for-each select="@*">
                <xsl:element name="{local-name(.)}">
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:transform>

Exercice

Opérer la transformation dans Apache NetBeans

Exercice

A l'aide du logiciel Apache NetBeans, écrire la transformation inverse de PLM_target.xml  vers PLM_source.xml 

Solution PLM_target_TO_PLM_source.xsl 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <!-- The 'match' attribute is used to associate a template with an XML element, say '/' as the root: -->
    <xsl:template match="/PLM">
        <PLM>
            <xsl:apply-templates select="Article"/>
            <xsl:text disable-output-escaping="yes"><!-- ... --></xsl:text> 
            <xsl:apply-templates select="Lien_de_nomenclature"/>
            <xsl:text disable-output-escaping="yes"><!-- ... --></xsl:text> 
        </PLM>
    </xsl:template>
    <xsl:template match="Article">
        <!-- L'élément 'Article' reste en tant que tel : -->
        <xsl:element name="{local-name()}">
            <!-- Conservation de l'attribut 'reference' pour l'élément 'Article' : -->
            <xsl:attribute name="reference">
                <xsl:value-of select="@reference"/>
            </xsl:attribute>
            <!-- Ajout de l'attribut 'designation' à l'élément 'Article' à partir
            du sous-élément 'designation' : -->
            <xsl:attribute name="designation">
                <xsl:value-of select="designation"/>
            </xsl:attribute>
            <!-- On itère sur tous les sous-éléments (bien que 'designation' soit traité juste avant
            pas de duplication néanmoins : -->
            <xsl:for-each select="*">
                <!-- '{local-name()}' ou '{local-name(.)}' pour accéder au nom de l'élément courant : -->                           
                <xsl:attribute name="{local-name()}">
                    <!-- Problème d'un sous-élément unique pour l'élément 'PF_ou_MP_ou_Piece_ou_SE' -->
                    <xsl:choose>
                        <!-- On teste si l'élément courant a un sous-élément, en l'occurrence
                        seul l'élément 'PF_ou_MP_ou_Piece_ou_SE' est dans ce cas : -->
                        <xsl:when test="*">
                            <!-- Le *NOM* du (premier) sous-élément est accédé via Xpath : -->
                            <xsl:value-of select="name(./*[1])"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <!-- La valeur de l'élément courant est exprimée via Xpath : -->
                            <xsl:value-of select="."/>
                        </xsl:otherwise>
                    </xsl:choose> 
                </xsl:attribute>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
    <xsl:template match="Lien_de_nomenclature">
        <!-- L'élément 'Lien_de_nomenclature' reste en tant que tel : -->
        <xsl:element name="{local-name()}">
            <xsl:for-each select="*">
                <xsl:attribute name="{local-name()}">
                    <xsl:value-of select="."/>
                </xsl:attribute>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:transform>
XML Linking language -XLink- et XPointer
  1. Tutoriel (w3schools)
  2. Tutoriel (autre)
  3. Tutoriel (autre autre)

Exemple XLink PLM_XLink.xml  CD100.xml  CH005.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Acces au "name space" 'xlink' : -->
<PLM_ xmlns:xlink="https://www.w3.org/1999/xlink">
    <!-- 'xlink:type="extended"': https://docstore.mik.ua/orelly/xml/xmlnut/ch10_04.htm -->
    <Articles_Liens_de_nomenclature xlink:type="extended" xlink:title="Articles et nomenclature de fabrication">
        <Articles xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Articles"/>
        <Liens_de_nomenclature xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Nomenclature_de_fabrication"/>
        <!-- 'xlink:label="..."' est un nom local pour creer ensuite les arcs : -->
        <Article xlink:type="locator" xlink:label="CD100" xlink:href="CD100.xml"/>
        <Article xlink:type="locator" xlink:label="CH005" xlink:href="CH005.xml"/>
        <Lien_de_nomenclature xlink:type="arc" xlink:from="CD100" xlink:to="CH005">
            <quantite_de_composition>1</quantite_de_composition>
        </Lien_de_nomenclature>    
    </Articles_Liens_de_nomenclature>
</PLM_>

Exemple XPointer PLM_XPointer.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Acces au "name space" 'xlink' : -->
<PLM xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude">
    <Articles xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Articles">
        <author xlink:type="simple" xlink:href="https://franckbarbier.com/img/Common/Franck.jpg"/>
        <!-- 'xlink:show="embed"' : le lien s'ouvre de facon embarquee -->
        <Type_CD100 xlink:type="simple" xlink:href="CD100.xml#xpointer(Article[@reference = 'CD100']/PF_ou_MP_ou_Piece_ou_SE)" xlink:show="embed"/>
        <!-- It relies on '<CH005 id="CH005">': -->
        <Article xlink:type="simple" xlink:href="CH005.xml#CH005" xlink:show="embed"/>
        <!-- ... -->
    </Articles>
    <xi:include href="CH005.xml" xpointer="xpointer()"/>
    <Liens_de_nomenclature xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Nomenclature_de_fabrication">
        <Lien_de_nomenclature>
            <compose xlink:type="simple" xlink:href="CD100.xml#xpointer(Article/designation[text()])"/>
            <!-- '|' means 'and': -->
            <composant xlink:type="simple" xlink:href="CH005.xml#xpointer(CH005/designation | CH005/PF_ou_MP_ou_Piece_ou_SE)"/>
            <quantite_de_composition>1</quantite_de_composition>
        </Lien_de_nomenclature>
        <!-- ... -->
    </Liens_de_nomenclature>
    <Postes_de_charge xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Postes_de_charge"/>
    <Gammes_de_fabrication xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Gammes_de_fabrication"/>
    <Mouvements_de_stock xlink:type="simple" xlink:href="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Mouvements_de_stock_et_inventaire"/>
</PLM>
XInclude

XInclude est l'inclusion « physique » d'éléments XML.

Exemple XInclude Saxon_XML.Java.zip

<?xml version="1.0" encoding="UTF-8"?>
<PLM xmlns:xi="http://www.w3.org/2001/XInclude">
    <!-- Toute l'arborescence et donc '<Articles> ... </Articles>' compris : -->
    <xi:include href="Articles.xml" parse="xml">
        <xi:fallback>'Articles.xml' raises problems?</xi:fallback>
    </xi:include>
    
    <!-- Apache Xerces in Java only supports xpointer="element(...)" -->
    
    <!-- La racine, i.e., 'Liens_de_nomenclature' : -->
    <!--<xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="element(/1)"/>-->
    
    <!-- Le 1er élément sous 'Liens_de_nomenclature' : -->
    <xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="element(/1/1)"/>
</PLM>
xmllint --xinclude .\PLM.xml

Articles.xml

<?xml version="1.0" encoding="UTF-8"?>
<Articles>
    <Article reference="CD100"
             designation="camion demenagement bleu"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="PF"/>
    <Article reference="CH005"
             designation="chassis monte"
             type_fabrication_achat="fabr. par lot"
             unite_achat_stock="unite"
             delai_en_semaine="2"
             lot_de_reapprovisionnement="200"
             stock_maxi="600"
             PF_ou_MP_ou_Piece_ou_SE="SE"/>
    <!-- ... -->
</Articles>

Liens_de_nomenclature.xml

<?xml version="1.0" encoding="UTF-8"?>
<Liens_de_nomenclature xml:id="RACINE"> <!-- Attention à bien conserver le suffixe 'xml:' devant 'id' -->
    <Lien_de_nomenclature xml:id="CD100-CH005"
                          compose="CD100"
                          composant="CH005"
                          quantite_de_composition="1">
        <FICTIF> <!-- Test pour 'xpointer="element(CD100-CH005/1)' -->
            <FICTIF>FICTIF</FICTIF>
        </FICTIF> 
    </Lien_de_nomenclature>
    <!-- ... -->
</Liens_de_nomenclature>

Exercice : tous les sous-éléments de la racine Liens_de_nomenclature

<xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="xpointer(/Liens_de_nomenclature/*)"/>

Exercice : le 1er sous-élément (* ⤳ tous) de l'élément ayant pour identité RACINE

<xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="element(RACINE/1)"/>

Exercice : le 1er sous-élément de l'élément ayant pour identité CD100-CH005 (bogue si aucun sous-élément !)

<xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="element(CD100-CH005/1)"/>

Exercice : tous les éléments FICTIF quelque soit leur niveau d'emboîtement ⤳ redondance !

<xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="xpointer(//FICTIF)"/>

Exercice : l'élément Lien_de_nomenclature dont la valeur de l'attribut compose est CD1000

<xi:include href="Liens_de_nomenclature.xml"
xpointer="xpointer(/Liens_de_nomenclature/Lien_de_nomenclature[@compose=&quot;CD100&quot;])"/>

Exercice : l'élément Lien_de_nomenclature dont la valeur de l'attribut compose est CD1000 et… ⤳ condition sur le contenu

<xi:include href="Liens_de_nomenclature.xml"
xpointer="xpointer(/Liens_de_nomenclature/Lien_de_nomenclature[@compose=&quot;CD100&quot;
and ./FICTIF/FICTIF/text()=&quot;FICTIF&quot;])"/>
<xi:include href="Liens_de_nomenclature.xml"
xpointer="xpointer(/Liens_de_nomenclature/Lien_de_nomenclature[@compose=&quot;CD100&quot;
and ./FICTIF/FICTIF[contains(.,&quot;FICTIF&quot;)]])"/>

Exercice : tous les éléments Lien_de_nomenclature quelque soit leur niveau ayant un sous-élément FICTIF lui même ayant un sous-élément FICTIF unique

<xi:include href="Liens_de_nomenclature.xml"
xpointer="xpointer(//Lien_de_nomenclature/FICTIF[count(FICTIF) = 1])"/>
Persistance

Système de gestion de base de données XML

Exemple JavaDB

CREATE TABLE PLM_XML_data(XML_data XML);
INSERT INTO PLM_XML_data(XML_data) VALUES(XMLPARSE(DOCUMENT '<PLM>
    <CD100>
        <reference>CD100</reference>
        <designation>camion demenagement bleu</designation>
        <type_fabrication_achat>fabr. par lot</type_fabrication_achat>
        <unite_achat_stock>unite</unite_achat_stock>
        <delai_en_semaine>2</delai_en_semaine>
        <!--<prix_standard></prix_standard>-->
        <lot_de_reapprovisionnement>200</lot_de_reapprovisionnement>
        <!--<stock_mini></stock_mini>-->
        <stock_maxi>600</stock_maxi>
        <!--<pourcentage_de_perte></pourcentage_de_perte>-->
        <!--<inventaire></inventaire>-->
        <PF_ou_MP_ou_Piece_ou_SE>PF</PF_ou_MP_ou_Piece_ou_SE>
    </CD100>
    <!--Etc.-->
</PLM>' PRESERVE WHITESPACE));
-- 'CLOB' <=> "Character Large OBject"
SELECT XMLSERIALIZE(XML_data AS CLOB) FROM PLM_XML_data;

Serialization XML

Exercice : tester l'API Java de serialization XML avec un objet de type Article

public class Article implements java.io.Serializable {

    transient public final String non_persistant = "Essai attribut 'transient'...";

    public enum Type_article {
        PF, MP, Piece, SE
    }
    // Default values for 'CD100':
    private final String _reference;
    private final String _designation;
    private String _type_fabrication_achat = "fabr. par lot";
    private String _unite_achat_stock = "unite";
    private int _delai_en_semaine = 2;
    private Float _prix_standard = null;
    private Integer _lot_de_reapprovisionnement = 200;
    private Integer _stock_mini = null;
    private Integer _stock_maxi = 600;
    private Float _pourcentage_de_perte = null;
    private String _inventaire = null;
    private Type_article _PF_ou_MP_ou_Piece_ou_SE = Type_article.PF;

    public Article(final String reference, final String designation) {
        _reference = reference;
        _designation = designation;
    }
    // Getters and setters here...
}