Remplacer chaque caractère par autre en gardant la structure [Résolu]

Remplacer chaque caractère par autre en gardant la structure [Résolu] - XML/XSL - Programmation

Marsh Posté le 14-10-2022 à 08:07:04    

Bien le bonjour la communauté  :hello: .
 
Je vous expose mon souci. Un nouveau challenge à votre sagacité... :lol:  
 Je travaille depuis quelques temps avec les principes XLST pour modifier des xmls qui sont la source de notre "Document Management System".
Notre business, par charte graphique, ne veut pas de bullet mais un tiret pour l'indentation (puce).
Je ne peux agir que sur le contenu des valeurs des noeuds (pas dans la config du tinymce ou du DMS).
Mon but étant de remplacer chaque occurrence bullet "" par un tiret (hyphen) tout en gardant la structure dans son noeud général "FreeText" (structure non modifiable).
A ce point, les remplacements s'effectuent mais il perd tous les noeuds enfants... :pfff:  
 
J'ai donc ceci comme xml, en entrée :
 

Citation :

<?xml version="1.0" encoding="UTF-8"?>
<form>
 <Document>
  <Header>
   <Message>
    <MessageOriginalName>QUICK_DOCUMENTS</MessageOriginalName>
   </Message>
  </Header>
 </Document>
 <Eform>
  <Selection_Heading1>FourthActor_1</Selection_Heading1>
  <Selection_Heading2>Beneficiary_2</Selection_Heading2>
  <Selection_Heading3>Beneficiary_1</Selection_Heading3>
  <FreeText mediatype="text/xslfo">
   <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:block>
     <fo:list-block margin-bottom="12pt" margin-top="12pt">
      <fo:list-item>
       <fo:list-item-label end-indent="label-end()">
        <fo:block>•</fo:block>
       </fo:list-item-label>
       <fo:list-item-body start-indent="body-start()">
        <fo:block>Ligne 1</fo:block>
       </fo:list-item-body>
      </fo:list-item>
      <fo:list-item>
       <fo:list-item-label end-indent="label-end()">
        <fo:block>•</fo:block>
       </fo:list-item-label>
       <fo:list-item-body start-indent="body-start()">
        <fo:block>Ligne 2</fo:block>
       </fo:list-item-body>
      </fo:list-item>
     </fo:list-block>
    </fo:block>
   </fo:block>
  </FreeText>
  <SelectedAll>true</SelectedAll>
 </Eform>
</form>


 
Et je voudrais par transformation xsl, ceci en sortie :
 

Citation :

<?xml version="1.0" encoding="UTF-8"?>
<form>
 <Document>
  <Header>
   <Message>
    <MessageOriginalName>QUICK_DOCUMENTS</MessageOriginalName>
   </Message>
  </Header>
 </Document>
 <Eform>
  <Selection_Heading1>FourthActor_1</Selection_Heading1>
  <Selection_Heading2>Beneficiary_2</Selection_Heading2>
  <Selection_Heading3>Beneficiary_1</Selection_Heading3>
  <FreeText mediatype="text/xslfo">
   <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:block>
     <fo:list-block margin-bottom="12pt" margin-top="12pt">
      <fo:list-item>
       <fo:list-item-label end-indent="label-end()">
        <fo:block>-</fo:block>
       </fo:list-item-label>
       <fo:list-item-body start-indent="body-start()">
        <fo:block>Ligne 1</fo:block>
       </fo:list-item-body>
      </fo:list-item>
      <fo:list-item>
       <fo:list-item-label end-indent="label-end()">
        <fo:block>-</fo:block>
       </fo:list-item-label>
       <fo:list-item-body start-indent="body-start()">
        <fo:block>Ligne 2</fo:block>
       </fo:list-item-body>
      </fo:list-item>
     </fo:list-block>
    </fo:block>
   </fo:block>
  </FreeText>
  <SelectedAll>true</SelectedAll>
 </Eform>
</form>


 
Grâce à mon dernier xsl ci-dessous, les remplacements s'effectuent mais il perd tous les noeuds enfants
 

Citation :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
 <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
 <xsl:param name="replace" select="'•'"/>
 <xsl:param name="by" select="'-'"/>
 <xsl:template match="*">
  <xsl:if test="/form/Document/Header/Message/MessageOriginalName[contains(., 'QUICK_DOCUMENTS')]">
   <xsl:choose>
    <xsl:when test="name()='FreeText'">
     <xsl:variable name="FT"><xsl:value-of select="string(/form/Eform/FreeText)"/></xsl:variable>
     <FreeText mediatype="text/xslfo"><xsl:value-of select="replace($FT, $replace, $by)"/></FreeText>
    </xsl:when>
    <xsl:otherwise>
     <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:if>
  <xsl:if test="not(/form/Document/Header/Message/MessageOriginalName[contains(., 'QUICK_DOCUMENTS')])">
   <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
  </xsl:if>
 </xsl:template>
 <xsl:template match="@*|text()|comment()|processing-instruction()">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>


 
J'obtiens ce mauvais xml généré :
 

Citation :

<?xml version="1.0" encoding="UTF-8"?>
<form>
 <Document>
  <Header>
   <Message>
    <MessageOriginalName>QUICK_DOCUMENTS</MessageOriginalName>
   </Message>
  </Header>
 </Document>
 <Eform>
  <Selection_Heading1>FourthActor_1</Selection_Heading1>
  <Selection_Heading2>Beneficiary_2</Selection_Heading2>
  <Selection_Heading3>Beneficiary_1</Selection_Heading3>
  <FreeText mediatype="text/xslfo">-Ligne 1-Ligne 2</FreeText>
  <SelectedAll>true</SelectedAll>
 </Eform>
</form>


 
Si une âme charitable voudrait bien m'aider, je le remercie déjà d'avance... :ange:


Message édité par smilodongor le 17-10-2022 à 09:52:02
Reply

Marsh Posté le 14-10-2022 à 08:07:04   

Reply

Marsh Posté le 14-10-2022 à 19:13:57    

Cale fait pas ça ?
https://stackoverflow.com/questions [...] ng-replace


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 15-10-2022 à 17:36:45    

Bonjour,
Cette feuille de style fait le taff :  
Elle copie tout a l'identique, sauf le cas particulier ou tu veux ta transformation/.
 

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet  
  3.  version="2.0"  
  4.  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  5.  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  6.  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  7.  exclude-result-prefixes="#all">
  8.  
  9.  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  10.  
  11.  <!-- identity copy par défaut -->
  12.  <xsl:template match="document-node()|node()|@*">
  13.    <xsl:copy>
  14.      <xsl:apply-templates select="node()|@*"/>
  15.    </xsl:copy>
  16.  </xsl:template>
  17.  
  18.  <!-- spécialisation pour le cas particulier -->
  19.  <xsl:template match="fo:block[not(*) and string(.)='•']">
  20.    <fo:block>-</fo:block>
  21.  </xsl:template>
  22.  
  23. </xsl:stylesheet>


 
Notes :  

  • il y a des choses qui ne sont pas acceptées en xsl 1.0 ( #all et replace() ) dans ton code original, [ton outil semble les accepter] d’où mon passage en xsl 2.0. De toute façon, le xsl 2.0 est le minimum pour arriver a faire des choses utilisables en XSL (on est bientôt au 4.0, c'est en cours de finalisation depuis un an). Si tu as vraiment des contraintes xsl 1.0 ceci devrait faire le taff:
Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet  
  3.  version="1.0"  
  4.  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  5.  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  6.  xmlns:fo="http://www.w3.org/1999/XSL/Format">
  7.  
  8.  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  9.  
  10.  <!-- identity copy par défaut -->
  11.  <xsl:template match="/|node()|@*">
  12.    <xsl:copy>
  13.      <xsl:apply-templates select="node()|@*"/>
  14.    </xsl:copy>
  15.  </xsl:template>
  16.  
  17.  <!-- spécialisation pour le cas particulier -->
  18.  <xsl:template match="fo:block[not(*) and string(.)='•']">
  19.    <xsl:element name="fo:block">-</xsl:element>
  20.  </xsl:template>
  21.  
  22. </xsl:stylesheet>


  • il est toujours bon de faire figurer les namespaces dont tu vas avoir besoin ( fo ) dans la partie xsl:stylesheet
  • match="fo:block[string(.)='•']" suffirait, mais match="fo:block[not(*) and string(.)='•']" optimise cela rejetant les fo:block contenant des éléments comme les deux premiers fo:block (imbriqués) de ton exemple, où la collecte de tout le texte des sous-éléments serait couteuse et inutile.


La même chose en xsl 3.0

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet  
  3.  version="3.0"  
  4.  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  5.  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  6.  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  7.  exclude-result-prefixes="#all">
  8.  
  9.  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  10.  <!-- identity copy par défaut via le mode par défaut-->
  11.  <xsl:mode on-no-match="shallow-copy"/>
  12.  
  13.  <!-- spécialisation pour le cas particulier -->
  14.  <xsl:template match="fo:block[not(*) and string(.)='•']">
  15.    <fo:block>-</fo:block>
  16.  </xsl:template>
  17.  
  18. </xsl:stylesheet>


 
A+,


Message édité par gilou le 15-10-2022 à 18:18:17

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

Marsh Posté le 15-10-2022 à 18:26:09    

Note que si tu es dans une boite, et que tu as professionnellement et couramment besoin de transformer du XML, tu devrais avoir l'outil standard pour (Oxygen XML Editor). Et une licence saxon, si tu as besoin de faire de la transfo xsl dans tes process (et pas seulement utiliser du xml transformé)
 
A+,


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

Marsh Posté le 17-10-2022 à 09:48:09    

Grand merci à vous 2.
 
D'abord @rufo : effectivement, je m'étais basé sur cet article (tu peux remarquer que mon xsl y ressemble).
 
Mais surtout @gilou.
Cela fonctionne très bien. Ce que j'ai apprécié, ce sont tes explications et conseils.
Parfait ...et bravo
Bonne continuation à ce forum avec des personnes de bonnes volonté.
 
Peut-être qu'un jour, je pourrais également aider à mon tour....

Reply

Sujets relatifs:

Leave a Replay

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