IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XML/XSL et SOAP Discussion :

[XSL] splitter une adresse trop longue sur deux lignes


Sujet :

XML/XSL et SOAP

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 62
    Points : 30
    Points
    30
    Par défaut [XSL] splitter une adresse trop longue sur deux lignes
    Bonjour à tous,

    Encore une fois je compte sur votre aide pour m'aider à répondre à un petit problème d'ordre technique...
    Au cour de mon travail je suis amené à devoir modifier un petit fichier XML exploitant du XSL, langage que je ne connaissait même pas il y à 2 jours...
    J'ai cherché à me débrouiller tous seul mais je sèche complètement et je passe énormément de temps sur un petit algo qui n'aurait pas du me prendre plus de 10min (si seulement c'était en java, python etc..)

    Alors voilà, la tache est relativement simple pour quelqu'un étant à l'aise avec le xsl:

    j'aimerais:
    ->si une adresse fais plus de 40 caractères:
    ---->la spliter sur deux lignes

    Bien sur, en faisant attention à ne pas couper un mot en deux, il faudrait aller à la ligne avec le mot complet, exemple :
    mot1 mot2 mot3 ... mot999
    mot5 mot6...

    et non pas :
    mot1 mot2 mot3 ... mo
    t4 mot5 mot6...




    j'ai déjà essayé plusieurs concepts mais rien n'a jamais fonctionné
    voici quelques exemples de mes essais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <xsl:template match="Address">
    		<xsl:call-template name="split">
    			<xsl:with-param name="add" select=".">
    				<Conv_Address1>
    					<xsl:value-of select="$a" />
    				</Conv_Address1>
    				<Conv_Address2>
    					<xsl:value-of select="$b" />
    				</Conv_Address2>
    			</xsl:with-param>
    		</xsl:call-template>
    	</xsl:template>
     
    	<xsl:template name="split">
    		<xsl:param name="Address"/>
    		<xsl:variable name="a" />
    		<xsl:variable name="b" />
    		<xsl:variable name="flag" select="true()"/>
     
    		<xsl:choose>
    			<xsl:when test="contains($Adress,' ')">
    				<xsl:if test="string-length(concat($a, substring-before($add,' '))) &gt; 40">
    					<xsl:value-of select="$flag = false()" />
    				</xsl:if>
    				<xsl:choose>
    					<xsl:when test="$flag = true()">
    						<xsl:value-of select="concat('$a =', substring-before($add,' '))" />
    					</xsl:when>
    					<xsl:when test="$flag = false()">
    						<xsl:value-of select="concat('$b =', substring-before($add,' '))" />
    					</xsl:when>
    				</xsl:choose>
     
    				<xsl:call-template name="split">
    					<xsl:with-param name="Address">
    						<xsl:if test="string-length(concat($a, substring-after($add,' '))) &gt; 40">
    							<xsl:value-of select="$flag = false()" />
    						</xsl:if>
    						<xsl:choose>
    							<xsl:when test="$flag = true()">
    								<xsl:value-of select="concat('$a =', substring-after($add,' '))" />
    							</xsl:when>
    							<xsl:when test="$flag = false()">
    								<xsl:value-of select="concat('$b =', substring-after($add,' '))" />
    							</xsl:when>
    						</xsl:choose>
    					</xsl:with-param>
    				</xsl:call-template>
     
    			</xsl:when>
    		</xsl:choose>
     
    	</xsl:template>
    ou bien encore :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    <xsl:template name="split">
    		<xsl:param name="Address"/>
    		<xsl:variable name="flag" select="true()"/>
     
    		<xsl:choose>
    			<xsl:when test="contains($Adress,' ')">
    				<xsl:if test="string-length(concat($Conv_Address1, substring-before($add,' '))) &gt; 40">
    					<xsl:value-of select="$flag = false()" />
    				</xsl:if>
    				<xsl:choose>
    					<xsl:when test="$flag = true()">
    						<Conv_Address1>
    							<xsl:value-of select="substring-before($add,' ')" />
    						</Conv_Address1>
    					</xsl:when>
    					<xsl:when test="$flag = false()">
    						<Conv_Address2>
    							<xsl:value-of select="substring-before($add,' ')" />
    						</Conv_Address2>
    					</xsl:when>
    				</xsl:choose>
     
    				<xsl:call-template name="split">
    					<xsl:with-param name="Address">
    						<xsl:if test="string-length(concat($Conv_Address1, substring-after($add,' '))) &gt; 40">
    							<xsl:value-of select="$flag = false()" />
    						</xsl:if>
    						<xsl:choose>
    							<xsl:when test="$flag = true()">
    								<Conv_Address1>
    									<xsl:value-of select="substring-after($add,' ')" />
    								</Conv_Address1>
    							</xsl:when>
    							<xsl:when test="$flag = false()">
    								<Conv_Address2>
    									<xsl:value-of select="substring-after($add,' ')" />
    								</Conv_Address2>
    							</xsl:when>
    						</xsl:choose>
    					</xsl:with-param>
    				</xsl:call-template>
     
    			</xsl:when>
    		</xsl:choose>
     
    	</xsl:template>
    Mais je crois bien que ma logique de programmation acquise au cour de dev en POO avec du java, python c# etc... ne coïncide pas du tout avec les principes du XSL que j'essaie le plus possible de comprendre...

    j'ai essayé de m'appuyer sur ceci : http://www.developpez.net/forums/d25...ath/split-xsl/

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Hello,

    parfois on comprend un peu mieux en se rappelant que XSLT n'est pas un langage de programmation, c'est un langage de transformation.
    Notamment, c'est un langage déclaratif, un peu comme un super-CSS.
    Notamment, on ne peut pas changer la valeur d'une variable. Ni utiliser une variable qui a été déclarée dans un autre scope.
    Et pour finir, il n'y a pas de notion de tableau ou de séquence, et on ne peut faire de boucle que sur les éléments du XML lus. On ne peut pas splitter une chaîne et boucler sur ses mots.


    Et tout ça rend ce que tu cherches à faire, bien plus compliqué que tu n'en auras l'habitude. Il aurait mieux valu un langage de programmation.

    La seule solution, comme tu l'as vu ailleurs, est de faire un template récursif.
    Par exemple il s'occuperait de construire la première ligne, en sélectionnant des mots au fur et à mesure, jusqu'à ce que le prochain mot ne rentre pas dans la limite de caractères.

    Le code de ce template serait ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <xsl:template name="write-first-line">
      <!-- pending-text contient le texte que nous n'avons pas encore sélectionné. Au début c'est l'adresse entière -->
      <xsl:param name="pending-text">
      <!-- selected-size contient la taille du texte déjà selectionné. Au début c'est zéro -->
      <xsl:param name="selected-size" select="0"/>
     
      <!-- On ne doit sélectionner du texte que s'il en reste à sélectionner -->
      <xsl:if test="string-length($pending-text) > 0">
     
        <!-- prochain mot -->
        <xsl:variable name="next-word" select="substring-before($pending-text, ' ')"/>
     
        <!-- Gestion de l'absence d'espace au début. Si on n'a encore rien sélectionné, on n'a pas à ajouter d'espace. Mais si on a déjà des mots, il faudra un espace avant d'ajouter le suivant. -->
        <xsl:variable name="separated-next-word">
          <!-- Un espace si nécessaire et rien sinon-->
          <xsl:if test="$selected-size > 0">
            <xsl:text> </xsl:text>
          </xsl:if>
          <xsl:value-of select="$next-word"/>
        </xsl:variable>
     
        <!-- On ne doit continuer que si le prochain mot peut être sélectionné. Sinon on a fini la première ligne -->
        <xsl:variable name="selected-size-with-word" select="$selected-size + string-length($separated-next-word)"/>
        <xsl:if test="$selected-size-with-word &lt; 40">
          <!-- Sélectionne le mot et continue -->
          <xsl:value-of select="$separated-next-word"/>
          <xsl:call-template name="write-first-line">
            <xsl:with-param name="pending-text" select="substring-after($pending-text, ' ')"/>
            <xsl:with-param name="selected-size" select="$selected-size-with-word"/>
          </xsl:call-template>
        </xsl:if>  
     
    </xsl:template>
    Et pourrait être utilisé comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:variable name="first-line">
      <xsl:call-template name="write-first-line">
        <xsl:with-param name="pending-text" select="."/>
      </xsl:call-template>
    </xsl:variable>
    Une fois que tu sais ce que tu dois écrire en première ligne, la nécessité ou non d'une deuxième ou que mettre dedans, devient facile à calculer.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 62
    Points : 30
    Points
    30
    Par défaut
    Tout d'abord un grand merci pour tes explications , je commençais à désespérer ^^'
    Néanmoins j'ai quelques problèmes pour implémenter ta fonction.



    Pour commencer, voici ce qui est dans le fichier XML et qui permet d'afficher l'adresse mais sur une seule ligne (que je dois donc modifier) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    	<!-- match a tag Date Address and transform it on 2 lines -->
    	<xsl:template match="Address">
    		<xsl:param name="add" select="."/>
    		<Conv_Address1>
    			<xsl:value-of select="$add" />
    		</Conv_Address1>
    		<Conv_Address2>
    			<!-- TODO LUX if address is too long, split on 2 lines -->
    			<!--<xsl:value-of select="$add" />-->
    		</Conv_Address2>
    	</xsl:template>
    __________ ADAPTATION __________

    Si j'ai bien compris, ceci permet de récupérer le contenu complet de la ligne 1 (bien entendu, le template write-first-line étant copié juste au dessus) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <xsl:variable name="first-line">
      <xsl:call-template name="write-first-line">
        <xsl:with-param name="pending-text" select="."/>
      </xsl:call-template>
    </xsl:variable>
    j'ai donc essayé plusieurs moyen pour adapter ta solution avec mon xml d'origine, mais sans réussite, par exemple :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    	<xsl:template name="write-first-line">
    		<!-- pending-text contient le texte que nous n'avons pas encore sélectionné. Au début c'est l'adresse entière -->
    		<xsl:param name="add">
    		<!-- selected-size contient la taille du texte déjà selectionné. Au début c'est zéro -->
    		<xsl:param name="selected-size" select="0"/>
     
    		<!-- On ne doit sélectionner du texte que s'il en reste à sélectionner -->
    		<xsl:if test="string-length($add) > 0">
     
    			<!-- prochain mot -->
    			<xsl:variable name="next-word" select="substring-before($add, ' ')"/>
     
    			<!-- Gestion de l'absence d'espace au début. Si on n'a encore rien sélectionné, on n'a pas à ajouter d'espace. Mais si on a déjà des mots, il faudra un espace avant d'ajouter le suivant. -->
    			<xsl:variable name="separated-next-word">
    				<!-- Un espace si nécessaire et rien sinon-->
    				<xsl:if test="$selected-size > 0">
    					<xsl:text> </xsl:text>
    				</xsl:if>
    				<xsl:value-of select="$next-word"/>
    			</xsl:variable>
     
    			<!-- On ne doit continuer que si le prochain mot peut être sélectionné. Sinon on a fini la première ligne -->
    			<xsl:variable name="selected-size-with-word" select="$selected-size + string-length($separated-next-word)"/>
    			<xsl:if test="$selected-size-with-word &lt; 40">
    				<!-- Sélectionne le mot et continue -->				
    				<xsl:value-of select="$separated-next-word"/>
    				<xsl:call-template name="write-first-line">
    					<xsl:with-param name="add" select="substring-after($add, ' ')"/>
    					<xsl:with-param name="selected-size" select="$selected-size-with-word"/>
    				</xsl:call-template>
    			</xsl:if>  
     
     
    		<!-- rajout d'un fin de if ici -->
    		</xsl:if> 
    	</xsl:template>
     
    	<!-- match a tag Date Address and transform it on 2 lines -->
    	<xsl:template match="Address">
    		<xsl:param name="add" select="."/>
    		<xsl:variable name="first-line">
    			<xsl:call-template name="write-first-line">
    				<xsl:with-param name="add" select="."/>
    			</xsl:call-template>
    		</xsl:variable>
     
    		<Conv_Address1>
    			<xsl:value-of select="$first-line" />
    		</Conv_Address1>
    		<Conv_Address2>
    			<xsl:value-of select="substring-after($add, $first-line)" />
    		</Conv_Address2>
    	</xsl:template>

    ou encore un modifiant directement la fonction pour écrire mot par mot dans mes balise :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    	<xsl:template name="Adress">
    		<!-- pending-text contient le texte que nous n'avons pas encore sélectionné. Au début c'est l'adresse entière -->
    		<xsl:param name="add">
    		<!-- selected-size contient la taille du texte déjà selectionné. Au début c'est zéro -->
    		<xsl:param name="selected-size" select="0"/>
     
    		<!-- On ne doit sélectionner du texte que s'il en reste à sélectionner -->
    		<xsl:if test="string-length($add) > 0">
     
    			<!-- prochain mot -->
    			<xsl:variable name="next-word" select="substring-before($add, ' ')"/>
     
    			<!-- Gestion de l'absence d'espace au début. Si on n'a encore rien sélectionné, on n'a pas à ajouter d'espace. Mais si on a déjà des mots, il faudra un espace avant d'ajouter le suivant. -->
    			<xsl:variable name="separated-next-word">
    				<!-- Un espace si nécessaire et rien sinon-->
    				<xsl:if test="$selected-size > 0">
    					<xsl:text> </xsl:text>
    				</xsl:if>
    				<xsl:value-of select="$next-word"/>
    			</xsl:variable>
     
    			<!-- On ne doit continuer que si le prochain mot peut être sélectionné. Sinon on a fini la première ligne -->
    			<xsl:variable name="selected-size-with-word" select="$selected-size + string-length($separated-next-word)"/>
    			<xsl:if test="$selected-size-with-word &lt; 40">
    				<!-- Sélectionne le mot et continue -->
     
    				<Conv_Address1>
    					<xsl:value-of select="$separated-next-word" />
    				</Conv_Address1>
     
    				<xsl:value-of select="$separated-next-word"/>
    				<xsl:call-template name="write-first-line">
    					<xsl:with-param name="add" select="substring-after($add, ' ')"/>
    					<xsl:with-param name="selected-size" select="$selected-size-with-word"/>
    				</xsl:call-template>
    			</xsl:if>  
     
    			<xsl:if test="$selected-size-with-word &gt; 40">
    				<!-- Sélectionne le mot et continue -->
     
    				<Conv_Address2>
    					<xsl:value-of select="$separated-next-word" />
    				</Conv_Address2>
     
    				<xsl:value-of select="$separated-next-word"/>
    				<xsl:call-template name="write-first-line">
    					<xsl:with-param name="add" select="substring-after($add, ' ')"/>
    					<xsl:with-param name="selected-size" select="$selected-size-with-word"/>
    				</xsl:call-template>
    			</xsl:if> 
     
    		</xsl:if> 
     
    	</xsl:template>
    Sans réussite non plus :-/

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Hello,

    On ne dit pas "sans succès", on dit : "le résultat est ça : <code du résultat> alors que je cherche à avoir ci : <résultat attendu>"

    Il est tout à fait possible qu'il faille arranger des choses dans mon code pour coller à ce que tu veux (ou que j'ai des bugs, c'est pas comme si j'avais testé .)
    Mais le code montre l'idée pour que tu puisses la reprendre. Il y a toute la structure et le raisonnement nécessaire, il ne reste qu'à peaufiner les détails. Et ça, c'est ton travail.

    Bien sûr je veux bien t'aider, mais tu dois montrer ce que tu as essayé par toi-même pour arranger les choses.

    Par exemple, bon, tu nous montres ton deuxième essaie que tu as essayé tout seul.
    Il fallait aussi dire ce qui ne te convient pas et ce que tu as fait pour essayer de comprendre comment le corriger. Mais c'est bien d'avoir essayé au moins une chose.
    Ce deuxième essai, à vu de nez, on voit qu'il ne peut pas marcher : il inclut la balise <Conv_Address1>, qui ne doit apparaître qu'une fois, dans un template qui va être parcouru plusieurs fois (puisqu'il s'appelle lui-même). Donc clairement ça va pas, l'idée ne peut pas marcher, à oublier.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. [XSL:FO] fusionner une cellule sur deux lignes.
    Par Luc Hermitte dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 03/07/2008, 11h33
  2. [XSL~FO] Comment couper une phrase trop longue?
    Par citizen87 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 11/03/2008, 15h29
  3. Couper une chaine trop longue ?
    Par ThitoO dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 27/03/2007, 09h40
  4. Réponses: 3
    Dernier message: 10/03/2007, 17h59
  5. ecrire sur deux ligne dans une button
    Par zidenne dans le forum Delphi
    Réponses: 5
    Dernier message: 27/07/2006, 10h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo