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 de Product Lifecycle Management -PLM- here…
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.
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, XSD…). Apache NetBeans permet également l'exécution de programmes XSLT.
A la découverte de Apache NetBeans pour XML…
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>
1ère approche (attributs) PLM_internal_DTD_1.xml
2e approche (éléments) PLM_external_DTD.xml
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 quelques données : d'autres articles, d'autres liens de nomenclature ainsi que des postes de charge here…, des gammes de fabrication here… et des mouvements de stock here…. Note : la rubrique
inventaire
est déjà prise en compte dans les articles.Exercice
A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_external_DTD.xml avec quelques données : d'autres articles, d'autres liens de nomenclature ainsi que des postes de charge here…, des gammes de fabrication here… et des mouvements de stock here…. Note : la rubrique
inventaire
est déjà prise en compte dans les articles.
Les espaces de nommage permettent de gérer les conflits de nommage dès lors que les données XML proviennent de plusieurs sources, souvent hétérogènes.
Exemple
<?xml version="1.0" encoding="UTF-8"?> <!-- The namespace URI is not used by the parser to look up information: --> <PLM xmlns:Articles="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Articles" xmlns:Nomenclature_de_fabrication="https://barbierdarnal.com/Enterprise_Architect/PLM/PLM.html#Nomenclature_de_fabrication"> <Articles:Article reference="C004" designation="chassis"/> <!-- Etc. --> <!-- Vide pour des raisons pedagogiques : --> <Nomenclature_de_fabrication:Lien_de_nomenclature/> <!-- Etc. --> </PLM>
Une DTD décrit un format auquel doit obéir un document XML.
DTD externalisée dans un fichier PLM.dtd
La DTD a été générée dans Apache NetBeans à partir de ce fichier source XML.
Validation PLM_external_DTD.xml
1ère approche (focus sur les attributs)
2e approche (focus sur les éléments)
Exercice DTD
A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_internal_DTD_1.xml en schématisant les données des postes de charge here… et des gammes de fabrication ici…
Exercice DTD
A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_internal_DTD_2.xml en schématisant les données des postes de charge here… et des gammes de fabrication ici…
Note
La correspondance
IDREF
/ID
est limitée. Typiquement, l'intégrité référentielle decomposant
versreference
empêche celle, par exemple, deOperation
versPoste de charge
si on a une propriété réputéeID
pourPoste de charge
. Bricolage possible : 2 fichiers DTD différents. Sous-note : l'utilisation deIDREFS
n'apporte rien à ce problème.
Le langage XSD produit un format auquel doit obéir un document XML. XSD est plus puissant que le langage DTD par le typage, la possibilité d'expression de tranformation, le fait que XSD soit écrit en XML lui-même, etc.
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 XSD
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 fichierConfinement.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 ici….
Exercice XSD
A l'aide du logiciel Apache NetBeans, opérer la validation du fichier
My_device.scxml
☛.XSD autorise la gestion des contraintes d'intégrité référentielle de façon plus poussée que DTD.
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>
A faire…
Opérer la validation dans Apache NetBeans.
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>
A faire…
Opérer la validation dans Apache NetBeans.
Exercice XSD
A l'aide du logiciel Apache NetBeans, compléter le fichier PLM_2.xsd en schématisant les données des postes de charge here… et des gammes de fabrication here…
Exercice XSD
A l'aide du logiciel Apache NetBeans, revoir le fichier PLM_1.xsd en créant le type
PF
à partir du type (pré-existant)Article
à reconsidérer. Utiliser la méta-balisecomplexContent
.
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 here…
XQuery utilise XPath. Rappel sur l'accès aux éléments d'un document XML avec XPath :
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 (voir fichier
Articles.xml
précédent)(: 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 (voir fichier
Articles.xml
précédent)(: 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 (voir fichier
Articles.xml
précédent)(: 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';
A faire…
Opérer les requêtes dans Apache NetBeans.
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>
A faire…
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))
Comme XSLT, XQuery autorise des transformations de XML vers XML.
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>
A faire…
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 .
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 sur XPath 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 et XQuery tous deux utilisent XPath comme sous-langage.
Exemple
Source XML 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>
A faire…
Opérer la transformation dans Apache NetBeans.
La transformation XML à XML est la plus « requise » dans le cadre de traitement massif de données : extraction, enrichissement, comparaison, fusion…
Exemple
Source XML 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>
A faire…
Opérer la transformation dans Apache NetBeans.
Exercice XSLT
A l'aide du logiciel Apache NetBeans, écrire la transformation inverse de PLM_target.xml vers PLM_source.xml .
XLink (relativement obsolète) et XPointer sont des outils XML « connexes » qui permettent de « relier » des éléments XML entre eux par navigation (liens hyper-texte) ou par référence.
Pour XLink, les attributs des éléments (liens hyper-texte) construits obéissent aux règles décrites ici…
XPointer s'appuie lui sur XPath pour cibler tout élément ou ensemble d'éléments d'un document XML.
XInclude quant à lui est l'inclusion « physique » d'éléments XML.
Exemple XLink PLM_XLink.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:title="Articles et nomenclature de fabrication" xlink:type="extended"> <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"> <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 --> <Article xlink:type="simple" xlink:href="CD100.xml#xpointer(reference('CD100'))" xlink:show="embed"/> <!-- It relies on '<CH005 id="CH005">': --> <Article xlink:type="simple" xlink:href="CH005.xml#CH005" xlink:show="embed"/> <!-- ... --> </Articles> <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(reference('CD100'))"/> <composant xlink:type="simple" xlink:href="CH005.xml"/> <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_>
Exemple XInclude
<?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> <!-- Tous les éléments 'Lien_de_nomenclature' quelque soit le niveau dans l'arborescence : --> <xi:include href="Liens_de_nomenclature.xml" parse="xml" xpointer="element(//Lien_de_nomenclature"/> </PLM>
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> <Lien_de_nomenclature compose="CD100" composant="CH005" quantite_de_composition="1"/> <!-- ... --> </Liens_de_nomenclature>
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;