Changer nom element et garder les namespaces

Changer nom element et garder les namespaces - XML/XSL - Programmation

Marsh Posté le 18-09-2020 à 10:54:30    

Bonjour à tous,
 
Je travaille en XSLT, et je souhaite recopier un élément et changer son nom. Sauf que je perds les namespaces (ajouté automatiquement par XSLT) dans la manip.
 
Dans ce cas là, j'ai bien un élément avec le nouveau nom et le contenu qu'il faut, mais il n'a pas les xlmns nécessaires.

Code :
  1. <xsl:for-each select="//unit | //reinforcement | //roe | //object">
  2.     <xsl:element name="object">
  3.         <xsl:copy-of select="@*"/>
  4.         <xsl:copy-of select="*"/>
  5.     </xsl:element>
  6. </xsl:for-each>


 
Et là, j'ai bien les namespaces ajoutés automatiquement, mais evidemment pas le bon nom.

Code :
  1. <xsl:for-each select="//unit | //reinforcement | //roe | //object">
  2.     <xsl:copy-of select="."/>
  3. </xsl:for-each>


 
Mon problème est que je ne peux pas me permettre d'ajout les namespaces à la main, parce qu'il y en a bien trop. Je cherche donc à automatiser, si quelqu'un serait capable de m'aider :).
 
Merci d'avance.

Reply

Marsh Posté le 18-09-2020 à 10:54:30   

Reply

Marsh Posté le 18-09-2020 à 11:12:43    

Si tu renommes sur place j'aurais tenté un truc tout bête comme ça moi :  
 
Renommer aaa en bbb :

<xsl:template match="aaa">
  <bbb>
    <xsl:apply-templates/>
  </bbb>
</xsl:template>


 
Voire :  

<xsl:template match="aaa">
    <xsl:element name="bbb" namespace="{namespace-uri()}">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>


 
Mais bon pas de raison que la première version touche les namespaces je pense.
 
 


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 11:56:41    

Ça ne fonctionne pas, voici avec des screens ce que j'obtiens, ce sera peut-être plus clair ? Je m'y suis peut-être mal pris.
 
La j'ai le namespace où il faut, mais pas d'élement renommé :
https://rehost.diberie.com/Uploads/0/20200918-115348-31208306-53f4-4bed-ae12-d30f4366a441.0.min.jpg
 
La, je n'ai pas le namespace automatiquement ajouté par XSLT :
https://rehost.diberie.com/Uploads/0/20200918-115442-f3ca8504-df47-470b-b360-894a250b29d7.0.min.jpg
 
Le apply-templates ne fonctionne pas du tout ici.
https://rehost.diberie.com/Uploads/0/20200918-115541-f389da93-91ab-416d-8201-2bcfb815b791.0.min.jpg

Reply

Marsh Posté le 18-09-2020 à 12:10:21    

Au lieu de mettre des screenshots d'un cas réel, tu devrais mettre du texte représentant un cas simple de ce que tu veux faire (et qui ne marche pas).

 

Pour transformer un document xml avec xslt c'est en général mieux d'utiliser d'utiliser <xsl:template match="....   et xsl:apply-templates   plutôt que de faire des <xsl:for-each

 

Exemple de ce que tu pourrais poster :

 


1. Un morceau d'xml type

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <root name="Coucou">
  3.    <foo id="42">
  4.        <bar id="42" />
  5.    </foo>
  6. </root>
 

Le bout d'xsl qui va avec :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet version="1.0"
  3.    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.    xmlns:exslt="urn:schemas-microsoft-com:xslt"
  5. >
  6.    <!-- generic rule : copy as if -->
  7.    <xsl:template match="@*|node()">
  8.        <xsl:copy>
  9.            <xsl:apply-templates select="@*|node()" />
  10.        </xsl:copy>
  11.    </xsl:template>
  12.  
  13.    <!-- specific rule : foo becomes FOO -->
  14.    <xsl:template match="foo">
  15.        <FOO>
  16.            <xsl:apply-templates/>
  17.        </FOO>
  18.    </xsl:template>
  19. </xsl:stylesheet>
 

Et ce que tu obtiens en sortie : xsltproc test.xsl test.xml

Code :
  1. <?xml version="1.0"?>
  2. <root name="Coucou">
  3.    <FOO xmlns:exslt="urn:schemas-microsoft-com:xslt">
  4.        <bar id="42"/>
  5.    </FOO>
  6. </root>

Message cité 1 fois
Message édité par Xavier_OM le 18-09-2020 à 12:29:05

---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 12:23:42    

Xavier_OM a écrit :

Au lieu de mettre des screenshots d'un cas réel, tu devrais mettre du texte représentant un cas simple de ce que tu veux faire (et qui ne marche pas).
 
Pour transformer un document xml avec xslt c'est en général mieux d'utiliser d'utiliser <xsl:template match="....   et xsl:apply-templates   plutôt que de faire des <xsl:for-each


 
Merci pour ton aide, j'ai appris XSLT seul alors je travaille probablement de la mauvaise manière.
 
Je cherche à prendre un XML entrant, qui correspond à un message A, et à le transformer en message B, avec une structure entièrement différente. Je n'arrive pas à poser le problème avec un cas simple comme tu le demandes. Les exemples simplifiés trouvés sur le net ne répondent pas à ma question.

Reply

Marsh Posté le 18-09-2020 à 12:28:16    

tahrky a écrit :


 
Merci pour ton aide, j'ai appris XSLT seul alors je travaille probablement de la mauvaise manière.
 
Je cherche à prendre un XML entrant, qui correspond à un message A, et à le transformer en message B, avec une structure entièrement différente. Je n'arrive pas à poser le problème avec un cas simple comme tu le demandes. Les exemples simplifiés trouvés sur le net ne répondent pas à ma question.


 
J'ai posté dans mon message précédent le genre de choses qu'il faudrait que tu postes ici pour qu'on comprenne ton problème :jap:


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 13:19:54    

Voilà mon fichier XML en entrée simplifié, je laisse l'arborescence pour montrer qu'il y a plusieurs endroits ou on peut trouver les elements.
 

Code :
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <nc1opordain:NC1_OPORD-AIN xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:nc1opordain="urn:fra:nc1:message:opordain">
  3.   <taskOrganisation>
  4.     <member>
  5.       <reinforcement xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement" xsi:type="nc1reinforcement:ReinforcementType">
  6.         <tacticalData>
  7.           <name>Nom-D1239</name>
  8.         </tacticalData>
  9.       </reinforcement>
  10.     </member>
  11.     <member>
  12.       <unit xmlns:nc1unit="urn:fra:nc1:objet:unit" xsi:type="nc1unit:UnitType">
  13.         <tacticalData>
  14.           <name>Nom-D1289</name>
  15.         </tacticalData>
  16.       </unit>
  17.     </member>
  18.   </taskOrganisation>
  19.   <_3_execution>
  20.     <D_artillerySupport>
  21.       <D1_fieldArtillery>
  22.         <reinforcements>
  23.           <reinforcement xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement" xsi:type="nc1reinforcement:ReinforcementType">
  24.             <tacticalData>
  25.               <comment>b</comment>
  26.             </tacticalData>
  27.           </reinforcement>
  28.  </reinforcements>
  29.       </D1_fieldArtillery>
  30.     </D_artillerySupport>
  31.   </_3_execution>
  32. </nc1opordain:NC1_OPORD-AIN>


 
Voici mon XSLT :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  3.     xmlns:xs="http://www.w3.org/2001/XMLSchema"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xmlns:fn="http://www.w3.org/2005/xpath-functions"
  6.     xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  7.     xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  8.     exclude-result-prefixes="xs fn"
  9.     version="2.0">
  10.     <xsl:output
  11.         method="xml"
  12.         encoding="UTF-8"
  13.         indent="yes"
  14.         omit-xml-declaration="no"
  15.     />
  16.     <xsl:strip-space elements="*" />
  17.    
  18.     <xsl:template match="nc1opordain:NC1_OPORD-AIN//@*|node()" mode="OpordAINToMessageLibre">
  19.         <xsl:element name="nc1messagelibre:NC1_MessageLibre">
  20.             <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
  21.             <xsl:copy-of select="@*"/>
  22.             <!--<xsl:copy-of copy-namespaces="no" select="extVersion"/>-->
  23.             <xsl:element name="subject">
  24.                 <xsl:value-of select="'OPORD-AIN'"/>
  25.             </xsl:element>
  26.             <xsl:element name="body">
  27.                 <xsl:element name="mixedText">
  28.                     <xsl:variable name="var" select="*"/>
  29.                     <xsl:apply-templates select="$var" mode="serialize"/>
  30.                 </xsl:element>
  31.                 <xsl:element name="objects">
  32.                     <xsl:for-each select="//unit | //reinforcement | //roe | //object">
  33.                         <xsl:apply-templates select="." />
  34.                     </xsl:for-each>
  35.                 </xsl:element>
  36.             </xsl:element>
  37.             <!-- On supprime extFunction -->
  38.             <!-- <xsl:copy-of copy-namespaces="no"  select="extFunction"/> -->
  39.         </xsl:element>
  40.     </xsl:template>
  41.    
  42.     <xsl:template match="*" mode="serialize">
  43.         <xsl:text>&lt;</xsl:text>
  44.         <xsl:value-of select="name()"/>
  45.         <xsl:text>&gt;</xsl:text>
  46.         <xsl:apply-templates mode="serialize"/>
  47.         <xsl:text>&lt;/</xsl:text>
  48.         <xsl:value-of select="name()"/>
  49.         <xsl:text>&gt;</xsl:text>
  50.     </xsl:template>
  51.    
  52.     <xsl:template match="text()" mode="serialize">
  53.         <xsl:value-of select="."/>
  54.     </xsl:template>
  55. </xsl:stylesheet>


 
Et voilà ce que je cherche à retrouver à la fin :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <nc1messagelibre:NC1_MessageLibre xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.                                   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre">
  4.    <subject>OPORD-AIN</subject>
  5.    <mixedText/>
  6.    <body>
  7.       <objects>
  8.  <object xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement" xsi:type="nc1reinforcement:ReinforcementType">
  9.   <tacticalData>
  10.     <name>Nom-D1239</name>
  11.   </tacticalData>
  12.  </object>
  13.  <object xmlns:nc1unit="urn:fra:nc1:objet:unit" xsi:type="nc1unit:UnitType">
  14.   <tacticalData>
  15.     <name>Nom-D1289</name>
  16.   </tacticalData>
  17.  </object>
  18.  <object xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement" xsi:type="nc1reinforcement:ReinforcementType">
  19.             <tacticalData>
  20.               <comment>b</comment>
  21.             </tacticalData>
  22.  </object>
  23.   </objects>
  24.    </body>
  25. </nc1messagelibre:NC1_MessageLibre>


 
J'espère que ce sera plus clair et suffisant :). J'aurais du mal à simplifier plus. J'ai laissé le minimum pour comprendre ma situation, en esperant que ce soit suffisant !
Merci beaucoup de tenter de m'aider en tout cas :).

Reply

Marsh Posté le 18-09-2020 à 14:18:09    

Parfait c'est beaucoup plus clair comme ça, je regarde ton xsl et je te dis ce que je trouve.


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 15:54:55    

Un truc comme ça devrait te mettre sur la bonne voie :  
 

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2.    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  3.        xmlns:xs="http://www.w3.org/2001/XMLSchema"
  4.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.        xmlns:fn="http://www.w3.org/2005/xpath-functions"
  6.        xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  7.        xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  8.        xmlns:nc1reinforcement="urn:fra:nc1:message:reinforcement"
  9.        exclude-result-prefixes="xs fn"
  10.        version="2.0">
  11.        <xsl:output
  12.            method="xml"
  13.            encoding="UTF-8"
  14.            indent="yes"
  15.            omit-xml-declaration="no"
  16.        />
  17.            <xsl:strip-space elements="*" />
  18.            <!-- identity rule : copy as if -->
  19.            <xsl:template match="@*|node()">
  20.                <xsl:copy>
  21.                    <xsl:apply-templates select="@*|node()" />
  22.                </xsl:copy>
  23.            </xsl:template>
  24.            <!-- what happens when we encounter a child of 'member' -->
  25.            <xsl:template match="//member/*" >
  26.                <xsl:element name="object">
  27.                    <!-- copy all attributes from matched node -->
  28.                    <xsl:copy-of select="@*"/>
  29.                    <!-- let the identity rule do the job for the rest -->
  30.                    <xsl:apply-templates />
  31.                </xsl:element>
  32.            </xsl:template>
  33.            <!-- everything starts here -->
  34.            <xsl:template match='/'>
  35.                <xsl:element name="nc1messagelibre">
  36.                    <xsl:element name='subject'>
  37.                        <xsl:value-of select='name(node())'/>
  38.                    </xsl:element>
  39.                    <xsl:element name='mixedText'/>
  40.                    <xsl:element name='body'>
  41.                        <xsl:element name='objects'>
  42.                            <!-- search for all 'member/xxx' anywhere below root -->
  43.                            <xsl:apply-templates select='//member/*' />
  44.                        </xsl:element>
  45.                    </xsl:element>
  46.                </xsl:element>
  47.            </xsl:template>
  48.        </xsl:stylesheet>


 
 
Une chose importante sur les namespaces : tous les nœuds héritent des attributs xmlns de leur parents
 
Donc ces deux choses sont strictement équivalentes :  

Code :
  1. <root xmlns:ct-ext="http://test.com/test-ext">
  2.  <ct-ext:case xmlns:ct-ext="http://test.com/test-ext">...</ct-ext:case>
  3. </root>
  4. <root xmlns:ct-ext="http://test.com/test-ext">
  5.  <ct-ext:case>...</ct-ext:case>
  6. </root>


 
Ça explique du coup que selon l'endroit où tu vas faire le <xsl-copy-of/> tu verras ou non apparaître les attributs xmlns des nœuds parents ou pas.


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 16:14:26    

Merci pour ton aide, certaines choses sont un peu plus clair dans mon esprit, cependant, je me retrouve avec ça en sortie, ce qui ne fonctionne pas.
 

Code :
  1. <object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2.                  xsi:type="nc1reinforcement:ReinforcementType">
  3.             <tacticalData xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement"
  4.                           xmlns:nc1opordain="urn:fra:nc1:message:opordain">
  5.                <name>Nom-D1239</name>
  6.             </tacticalData>
  7.          </object>


 
c'est objet qui devrait avoir le xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement", pas tacticalData. Le XSD de contrôle n'aime pas ça, et je n'arrive pas à remonter d'au moins un niveau l'information.  
 
Merci encore beaucoup pour ton aide :).
 
EDIT : Je peux régler le probleme en faisant une recherche de tous les namespaces dans le fichier, et les recopier comme attribut, je devrais y arriver. Cependant je reste curieux de savoir s'il est possible de faire ce que je cherche à faire ^^.  
 
Merci beaucoup pour ton aide en tout cas.

Message cité 2 fois
Message édité par tahrky le 18-09-2020 à 16:34:13
Reply

Marsh Posté le 18-09-2020 à 16:14:26   

Reply

Marsh Posté le 18-09-2020 à 16:35:16    

tahrky a écrit :

Merci pour ton aide, certaines choses sont un peu plus clair dans mon esprit, cependant, je me retrouve avec ça en sortie, ce qui ne fonctionne pas.
 

Code :
  1. <object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2.                  xsi:type="nc1reinforcement:ReinforcementType">
  3.             <tacticalData xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement"
  4.                           xmlns:nc1opordain="urn:fra:nc1:message:opordain">
  5.                <name>Nom-D1239</name>
  6.             </tacticalData>
  7.          </object>


 
c'est objet qui devrait avoir le xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement", pas tacticalData. Le XSD de contrôle n'aime pas ça, et je n'arrive pas à remonter d'au moins un niveau l'information. Il pourrait être au niveau de l'élément messageLibre, ça ne serait pas gênant, mais je ne peux pas me permettre de le mettre à la main, j'ai plusieurs dizaines de namespace à traiter, et je ne les connais pas à l'avance.  
 
Merci encore beaucoup pour ton aide :).


 
Tu peux peut-être éviter que les namespaces n'apparaissent en mettant copy-namespaces="no" dans la identity rule  

Code :
  1. <xsl:template match="@*|node()">
  2.    <xsl:copy copy-namespaces="no" >
  3.        <xsl:apply-templates select="@*|node()" />
  4.    </xsl:copy>
  5. </xsl:template>


vu que c'est elle qui copie tacticalData


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 18-09-2020 à 19:24:19    

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.   xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xmlns:fn="http://www.w3.org/2005/xpath-functions"
  7.   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  8.   xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  9.   xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement"
  10.   xmlns:nc1unit="urn:fra:nc1:objet:unit"
  11.   exclude-result-prefixes="xs fn nc1reinforcement nc1unit nc1opordain"
  12.   version="2.0">
  13.  
  14.   <xsl:template match="/|@*|*" priority="-1">
  15.     <xsl:apply-templates select="@*|*"/>
  16.   </xsl:template>
  17.  
  18.   <xsl:template match="nc1opordain:NC1_OPORD-AIN">
  19.     <nc1messagelibre:NC1_MessageLibre>
  20.       <subject>OPORD-AIN</subject>
  21.       <mixedText/>
  22.       <body>
  23.         <objects>
  24.           <xsl:apply-templates select="*"/>
  25.         </objects>
  26.       </body>
  27.     </nc1messagelibre:NC1_MessageLibre>
  28.   </xsl:template>
  29.  
  30.   <xsl:template match="(reinforcement|unit)[tacticalData]">
  31.     <xsl:if test="@xsi:type">
  32.       <object>
  33.         <xsl:namespace name="{substring-before(@xsi:type, ':')}" select="concat('urn:fra:nc1:objet:', local-name())"/>
  34.         <xsl:copy-of select="@xsi:type"/>
  35.         <xsl:copy-of select="tacticalData" copy-namespaces="no"/>
  36.       </object>
  37.     </xsl:if>
  38.   </xsl:template>
  39.  
  40. </xsl:stylesheet>


 
Le seul truc un poil coton, c'est que la transfo a tendance a perdre la déclaration du namespace de la valeur d'attribut ou la mettre sur l'élément suivant si on ne le fait pas explicitement à la main.
Testé sous Oxygen. Le Texte/Grille d'une de tes captures d'écran me laisse supposer que c'est ce que tu utilises. Si oui, pourquoi ne pas faire du xsl 3.0, c'est quand même bien plus pratique.  
Bon après, tu adaptes si il y a des choses plus paramétrées et simplifiées dans ce que tu fais.
Typiquement j'ai mis <xsl:template match="(reinforcement|unit)[tacticalData]"> mais ça pourrait tout aussi bien être <xsl:template match="*[tacticalData]"> je ne connais pas assez bien tes données pour trancher.
 
Un exemple de la manière dont j'aurais pu écrire ça en 3.0

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.   xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  7.   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  8.   exclude-result-prefixes="xs nc1opordain"
  9.   version="3.0">
  10.  
  11.   <xsl:mode name="#default" on-no-match="shallow-skip"/>
  12.   <xsl:strip-space elements="*"/>
  13.   <xsl:output indent="true"/>
  14.  
  15.   <xsl:template match="/nc1opordain:*">
  16.     <xsl:element name="nc1messagelibre:NC1_MessageLibre">
  17.       <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
  18.       <subject><xsl:value-of select="substring-after(local-name(), 'NC1_')"/></subject>
  19.       <mixedText/>
  20.       <body>
  21.         <objects>
  22.           <xsl:apply-templates select="descendant::*[not(empty(@xsi:type))][tacticalData]" mode="tactical"/>
  23.         </objects>
  24.       </body>
  25.       </xsl:element>
  26.   </xsl:template>
  27.  
  28.   <xsl:template match="*" mode="tactical">
  29.     <object>
  30.       <xsl:variable name="xsi-type-value-prefix" select="substring-before(@xsi:type, ':')" as="xs:string"/>
  31.       <xsl:namespace name="{$xsi-type-value-prefix}" select="namespace-uri-for-prefix($xsi-type-value-prefix, .)"/>
  32.       <xsl:copy-of select="@xsi:type"/>
  33.       <xsl:copy-of select="tacticalData" copy-namespaces="no"/>
  34.     </object>
  35.   </xsl:template>
  36.  
  37. </xsl:stylesheet>


tahrky a écrit :

Merci pour ton aide, certaines choses sont un peu plus clair dans mon esprit, cependant, je me retrouve avec ça en sortie, ce qui ne fonctionne pas.
 

Code :
  1. <object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2.                  xsi:type="nc1reinforcement:ReinforcementType">
  3.             <tacticalData xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement"
  4.                           xmlns:nc1opordain="urn:fra:nc1:message:opordain">
  5.                <name>Nom-D1239</name>
  6.             </tacticalData>
  7.          </object>


 
c'est objet qui devrait avoir le xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement", pas tacticalData. Le XSD de contrôle n'aime pas ça, et je n'arrive pas à remonter d'au moins un niveau l'information.

Pour xmlns:nc1opordain, c'est parce que tu crée object (et toute sa hiérarchie au dessus) comme un nouvel élément, et de ce fait, il n'est pas lié aux namespaces de l'arbre de départ, qu'il ne connait pas. Mais la transformation, elle, elle sait que le namespace nc1opordain a été déclaré dans le contexte de tacticalData (qui lui figurait dans l'arbre de départ) et qu'il ne figure pas dans le contexte des ancêtres de tacticalData en sortie, donc elle fait alors la déclaration, car c'est la première opportunité qu'elle a de le faire. Pour éviter la déclaration du namespace en sortie, il faut faire un copy-namespaces a no, ce qui évitera d'avoir les déclarations de namespaces déclarés dans le contexte d'entrée et pas utilisés dans celui de sortie.
C'est aussi ce qui s'applique pour xmlns:nc1reinforcement et xmlns:nc1unit qui au traitement de tacticalData ont été déclarés dans le contexte d'entrée, mais pas encore dans celui de sortie.
Sur un nouvel élément tel que object ici, il faut directement faire la déclaration du namespace avec xsl:namespace. Et alors le namespace sera déclaré dans le contexte de sortie "au bon moment".
 
A+,

Message cité 1 fois
Message édité par gilou le 19-09-2020 à 19:12:52

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-09-2020 à 08:46:23    

gilou a écrit :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.   xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xmlns:fn="http://www.w3.org/2005/xpath-functions"
  7.   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  8.   xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  9.   xmlns:nc1reinforcement="urn:fra:nc1:objet:reinforcement"
  10.   xmlns:nc1unit="urn:fra:nc1:objet:unit"
  11.   exclude-result-prefixes="xs fn nc1reinforcement nc1unit nc1opordain"
  12.   version="2.0">
  13.  
  14.   <xsl:template match="/|@*|*" priority="-1">
  15.     <xsl:apply-templates select="@*|*"/>
  16.   </xsl:template>
  17.  
  18.   <xsl:template match="nc1opordain:NC1_OPORD-AIN">
  19.     <nc1messagelibre:NC1_MessageLibre>
  20.       <subject>OPORD-AIN</subject>
  21.       <mixedText/>
  22.       <body>
  23.         <objects>
  24.           <xsl:apply-templates select="*"/>
  25.         </objects>
  26.       </body>
  27.     </nc1messagelibre:NC1_MessageLibre>
  28.   </xsl:template>
  29.  
  30.   <xsl:template match="(reinforcement|unit)[tacticalData]">
  31.     <xsl:if test="@xsi:type">
  32.       <object>
  33.         <xsl:namespace name="{substring-before(@xsi:type, ':')}" select="concat('urn:fra:nc1:objet:', local-name())"/>
  34.         <xsl:copy-of select="@xsi:type"/>
  35.         <xsl:copy-of select="tacticalData" copy-namespaces="no"/>
  36.       </object>
  37.     </xsl:if>
  38.   </xsl:template>
  39.  
  40. </xsl:stylesheet>


 
Le seul truc un poil coton, c'est que la transfo a tendance a perdre la déclaration du namespace de la valeur d'attribut ou la mettre sur l'élément suivant si on ne le fait pas explicitement à la main.
Testé sous Oxygen. Le Texte/Grille d'une de tes captures d'écran me laisse supposer que c'est ce que tu utilises. Si oui, pourquoi ne pas faire du xsl 3.0, c'est quand même bien plus pratique.  
Bon après, tu adaptes si il y a des choses plus paramétrées et simplifiées dans ce que tu fais.
Typiquement j'ai mis <xsl:template match="(reinforcement|unit)[tacticalData]"> mais ça pourrait tout aussi bien être <xsl:template match="*[tacticalData]"> je ne connais pas assez bien tes données pour trancher.
 
Un exemple de la manière dont j'aurais pu écrire ça en 3.0

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.   xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  7.   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  8.   exclude-result-prefixes="xs nc1opordain"
  9.   version="3.0">
  10.  
  11.   <xsl:mode name="#default" on-no-match="shallow-skip"/>
  12.   <xsl:strip-space elements="*"/>
  13.   <xsl:output indent="true"/>
  14.  
  15.   <xsl:template match="/nc1opordain:*">
  16.     <xsl:element name="nc1messagelibre:NC1_MessageLibre">
  17.       <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
  18.       <subject><xsl:value-of select="substring-after(local-name(), 'NC1_')"/></subject>
  19.       <mixedText/>
  20.       <body>
  21.         <objects>
  22.           <xsl:apply-templates select="descendant::*[not(empty(@xsi:type))][tacticalData]" mode="tactical"/>
  23.         </objects>
  24.       </body>
  25.       </xsl:element>
  26.   </xsl:template>
  27.  
  28.   <xsl:template match="*" mode="tactical">
  29.     <object>
  30.       <xsl:variable name="xsi-type-value-prefix" select="substring-before(@xsi:type, ':')" as="xs:string"/>
  31.       <xsl:namespace name="{$xsi-type-value-prefix}" select="namespace-uri-for-prefix($xsi-type-value-prefix, .)"/>
  32.       <xsl:copy-of select="@xsi:type"/>
  33.       <xsl:copy-of select="tacticalData" copy-namespaces="no"/>
  34.     </object>
  35.   </xsl:template>
  36.  
  37. </xsl:stylesheet>




 

gilou a écrit :

Pour xmlns:nc1opordain, c'est parce que tu crée object (et toute sa hiérarchie au dessus) comme un nouvel élément, et de ce fait, il n'est pas lié aux namespaces de l'arbre de départ, qu'il ne connait pas. Mais la transformation, elle, elle sait que le namespace nc1opordain a été déclaré dans le contexte de tacticalData (qui lui figurait dans l'arbre de départ) et qu'il ne figure pas dans le contexte des ancêtres de tacticalData en sortie, donc elle fait alors la déclaration, car c'est la première opportunité qu'elle a de le faire. Pour éviter la déclaration du namespace en sortie, il faut faire un copy-namespaces a no, ce qui évitera d'avoir les déclarations de namespaces déclarés dans le contexte d'entrée et pas utilisés dans celui de sortie.
C'est aussi ce qui s'applique pour xmlns:nc1reinforcement et xmlns:nc1unit qui au traitement de tacticalData ont été déclarés dans le contexte d'entrée, mais pas encore dans celui de sortie.
Sur un nouvel élément tel que object ici, il faut directement faire la déclaration du namespace avec xsl:namespace. Et alors le namespace sera déclaré dans le contexte de sortie "au bon moment".
 
A+,


 
Merci beaucoup, c'est plus clair dans ma tête, et j'ai un code qui fonctionne comme je cherchais à le faire ! :).
Oui, j'utilise Oxygen, mais en version 16, qui ne permet de faire fonctionner que XSLT2. De toute façon, l'environnement de travail ne supporte pas XSLT3 actuellement, ce qui me restreint beaucoup.
 
Merci Xavier_OM et Gilou pour votre aide précieuse !  :jap:

Reply

Marsh Posté le 21-09-2020 à 10:11:12    

Gilou c'est l'meilleur de toute façon :D  :jap:


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 21-09-2020 à 22:18:01    

C'est ce qui me fait bouffer, le xsl.  
En me relisant, je vois que je peux écrire cela en 2.0 et un chouia plus fonctionnel :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4.   xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xmlns:nc1opordain="urn:fra:nc1:message:opordain"
  7.   xmlns:nc1messagelibre="urn:fra:nc1:message:messagelibre"
  8.   exclude-result-prefixes="xs nc1opordain"
  9.   version="2.0">
  10.  
  11.   <xsl:strip-space elements="*"/>
  12.   <xsl:output indent="true"/>
  13.  
  14.   <!-- shallow-skip by default -->
  15.   <xsl:template match="/|@*|*">
  16.     <xsl:apply-templates select="@*|*"/>
  17.   </xsl:template>
  18.  
  19.   <xsl:template match="/nc1opordain:*">
  20.     <xsl:element name="nc1messagelibre:NC1_MessageLibre">
  21.       <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
  22.       <subject><xsl:value-of select="substring-after(local-name(), 'NC1_')"/></subject>
  23.       <mixedText/>
  24.       <body>
  25.         <objects>
  26.           <xsl:apply-templates/>
  27.         </objects>
  28.       </body>
  29.       </xsl:element>
  30.   </xsl:template>
  31.  
  32.   <xsl:template match="*[not(empty(@xsi:type))][tacticalData]">
  33.     <object>
  34.       <xsl:variable name="xsi-type-value-prefix" select="substring-before(@xsi:type, ':')" as="xs:string"/>
  35.       <xsl:namespace name="{$xsi-type-value-prefix}" select="namespace-uri-for-prefix($xsi-type-value-prefix, .)"/>
  36.       <xsl:copy-of select="@xsi:type, tacticalData" copy-namespaces="no"/>
  37.     </object>
  38.   </xsl:template>
  39.  
  40. </xsl:stylesheet>


A+,


Message édité par gilou le 21-09-2020 à 22:19:09

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-09-2020 à 09:28:16    

J'en ai fait durant 8-12 mois ya 12 ans donc j'avoue c'est pas aussi fluide pour moi  :D


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed