2017-10-02 14 views
0

La condition 'when' n'identifie pas correctement les éléments vides. La sortie désirée devrait afficher l'attribut 'EMPTYAddress2'. J'ai essayé différentes conditions «non» mais pas de chance. S'il vous plaît, aidez, je suis un débutant. J'utilise Oxygen XML Developer et aucune erreur n'est renvoyée.XSL lorsque la condition n'identifie pas l'élément vide

fichier source XML:

<InterfaceData> 
    <OBJECT_ACTION_ID>16283</OBJECT_ACTION_ID> 
    <Employee> 
     <Employee> 
      <EmployeeBasic> 
       <EmployeeNo>50064</EmployeeNo> 
      </EmployeeBasic> 
      <EmployeeBasic_DateMarriageCeased> 
       <PersonDetailsRecords> 
        <PersonDetails> 
         <DateMarriageCeased/> 
        </PersonDetails> 
       </PersonDetailsRecords> 
      </EmployeeBasic_DateMarriageCeased> 
      <EmployeeAddress> 
       <AddressRecords> 
        <AddressDetails> 
         <Address1>Line1</Address1> 
         <Address2/> 
         <Address3>Line3</Address3> 
         <Address4>Line4</Address4> 
         <Postcode>Postcode</Postcode> 
        </AddressDetails> 
       </AddressRecords> 
      </EmployeeAddress> 
     </Employee> 
    </Employee> 
</InterfaceData> 

feuille de style XSL:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:template match="/"> 
     <xsl:for-each-group select="//InterfaceData" group-by="OBJECT_ACTION_ID"> 
      <!-- Employee --> 
      <EmployeeAddress> 
       <xsl:for-each select="current-group()//AddressDetails"> 
        <xsl:call-template name="CGIderiveAddress"> 
         <xsl:with-param name="myVarAddress1" select="current-group()//Address1/text()"/> 
         <xsl:with-param name="myVarAddress2" select="current-group()//Address2/text()"/> 
         <xsl:with-param name="myVarAddress3" select="current-group()//Address3/text()"/> 
         <xsl:with-param name="myVarAddress4" select="current-group()//Address4/text()"/> 
         <xsl:with-param name="myVarPostcode" select="current-group()//Postcode/text()"/> 
        </xsl:call-template> 
       </xsl:for-each> 
      </EmployeeAddress> 
     </xsl:for-each-group> 
    </xsl:template> 
    <xsl:template name="CGIderiveAddress"> 
     <xsl:param name="myVarAddress1"/> 
     <xsl:param name="myVarAddress2"/> 
     <xsl:param name="myVarAddress3"/> 
     <xsl:param name="myVarAddress4"/> 
     <xsl:param name="myVarPostcode"/> 
     <xsl:attribute name="Address1"> 
      <xsl:value-of select="$myVarAddress1"/> 
     </xsl:attribute> 
     <xsl:choose> 
      <!-- Address Line 2 is empty and Adress Line 3 exists --> 
      <xsl:when test="$myVarAddress2 = ''"> 
       <xsl:attribute name="EMPTYAddress2"> 
        <xsl:value-of select="'EMPTYAddress2'"/> 
       </xsl:attribute> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:attribute name="NotEMPTYAddress2"> 
        <xsl:value-of select="'NotEMPTYAddress2'"/> 
       </xsl:attribute> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

xsl: output:

<?xml version="1.0" encoding="UTF-8"?> 
<EmployeeAddress Address1="Line1" 
       NotEMPTYAddress2="NotEMPTYAddress2"/> 
+1

L'utilisation de 'current-group()' quand vous n'avez pas de 'for-each-group' n'a aucun sens. –

+1

Je crains qu'un 'for-each-group' sans" group-by' "ou" group-adjacent "ou" group-starting-with "/" ending-with "n'a pas de sens non plus. Si le groupement n'est pas pertinent que de prendre le temps de préparer un échantillon minimal mais complet nous permettant de reproduire le problème, avec l'entrée que vous avez, la sortie que vous obtenez et le résultat que vous voulez. –

+0

En outre, vous faites 'for-each-group' sur' AddressRecords' qui est l'élément racine, et il n'y en aura jamais qu'un seul. Ce n'est pas quelque chose que vous voudriez grouper. –

Répondre

1

/text() est presque en utilisant toujours une erreur. Dans ce cas, si l'élément Address2 existe et n'a pas d'enfants, alors Address2/text() est une séquence vide (PAS un noeud avec une valeur de chaîne de longueur nulle!); Lorsque vous testez une séquence vide pour l'égalité avec n'importe quoi, même une chaîne de longueur nulle, le résultat est toujours faux.

Je pense que le modèle CGIderiveAddress s'attend à ce que tous ses paramètres soient des chaînes, donc ce serait une bonne idée de le déclarer comme tel en utilisant as = "xs: string" sur l'élément xsl:param. Si vous l'aviez fait, vous recevriez un message d'erreur indiquant que vous fournissiez une séquence vide là où elle n'est pas autorisée. Les messages d'erreur sont toujours meilleurs que les résultats incorrects, et un bon moyen de les atteindre est de déclarer les types de toutes vos variables et (en particulier) les paramètres.

Ensuite, utilisez simplement <xsl:with-param select="current-group()//Address2"/>. Puisque la valeur attendue est une chaîne, l'élément Address2 sera atomisé et transformé en une chaîne, qui sera une chaîne de longueur nulle si l'élément Address2 est vide. Si vous souhaitez également une chaîne de longueur nulle lorsque Address2 est absent, utilisez string(current-group()//Address2).

En regardant le code plus attentivement, il y a un autre bug flagrant ici:

<xsl:for-each select="current-group()//AddressDetails"> 
    <xsl:call-template name="CGIderiveAddress"> 
     <xsl:with-param name="myVarAddress1" 
      select="current-group()//Address1/text()"/> 

Je suis sûr que vous voulez vraiment passer la valeur Address1 pour les addressdetails que vous traitez actuellement, ne sont pas tous les Address1 valeurs pour le groupe d'éléments actuel.C'est simplement

<xsl:with-param name="myVarAddress1" select="Address1"/> 
+0

Brillant, merci pour l'explication. Donc bénéfique pour un débutant comme moi! – murfy92

+0

J'ai essayé de définir le type de paramètre comme suggéré: 'cependant, je reçois une erreur ** XPST0081: Le préfixe d'espace de noms 'xs' n'a pas été déclaré ** – murfy92

+1

Alors déclarez-le, chère Murfy ... Vous avez besoin de 'xmlns: xs =" http://www.w3.org/2001/XML/Schema "' sur l'élément xsl: stylesheet. –

1

Vous définissez myVarAddress2 comme si ...

<xsl:with-param name="myVarAddress2" select="current-group()//Address2/text()"/> 

Mais Address2 dans votre exemple XML d'entrée ne contient aucun noeud de texte enfant, le paramètre $myVarAddress2 contient donc une séquence vide. Une séquence vide n'est pas la même qu'une chaîne vide, et donc le test $myVarAddress2 = '' est faux.

Au lieu de cela, que vous utilisez XSLT 2.0, vous pouvez le faire ....

<xsl:when test="empty($myVarAddress2)"> 

Notez que je ne vois pas comment le regroupement entre dans votre XSLT, notamment parce que InterfaceData est l'élément racine .

En outre, pour le XSLT indiqué dans votre question, vous pouvez simplifier les paramètres comme si ...

<xsl:with-param name="myVarAddress2" select="Address2/text()"/>