2017-04-03 3 views
0

Je cherche de l'aide. J'ai un formulaire XFA (basé sur XML) avec une liste déroulante, qui contient un affichage et enregistre la valeur par élément. Comme la liste peut être très longue, j'essaie de la filtrer en utilisant XSLT 1.0.Comment filtrer deux arbres xml à la fois en utilisant XSLT 1.0?

Le XML source drom le menu déroulant peut ressembler à ceci:

<?xml version="1.0" encoding="UTF-8"?> 
<field name="DropDownList" xmlns="http://www.xfa.org/schema/xfa-form/2.8/"> 
    <!-- Displayed items to be filtered --> 
    <items xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
     <text>Lorem Ipsum 0030</text> 
     <text>Lorem Ipsum 0060</text> 
     <text>Lorem Ipsum 0070</text> 
     <text>Lorem Ipsum 0080</text> 
     <text>Lorem Ipsum 0100</text> 
     <text>Lorem Ipsum 0110</text> 
     <text>Lorem Ipsum 0120</text> 
     <text>Lorem Ipsum 0130</text> 
     <text>Lorem Ipsum 0140</text> 
    </items> 
    <!-- Hidden save items to be filtered too --> 
    <items save="1" presence="hidden" xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
     <text>item0</text> 
     <text>item1</text> 
     <text>item2</text> 
     <text>item3</text> 
     <text>item4</text> 
     <text>item5</text> 
     <text>item6</text> 
     <text>item7</text> 
     <text>item8</text> 
     <text>item9</text> 
    </items> 
</field> 

Mon style actuel semble ainsi:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xfa="http://www.xfa.org/schema/xfa-form/2.8/" xml:space="preserve"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" standalone="yes"/> 
    <xsl:template match="/"> 
     <field name="DropDownList"> 
      <xsl:apply-templates/> 
     </field> 
    </xsl:template> 
    <xsl:template match="/*[local-name()='field']/*[local-name()='items']" > 
     <items xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
      <xsl:for-each select="./*[local-name()='text']"> 
       <xsl:if test="contains(., '01')"> 
        <text> 
         <xsl:value-of select="."/> 
        </text> 
       </xsl:if> 
      </xsl:for-each> 
     </items> 
    </xsl:template> 
</xsl:stylesheet> 

Ce que je besoin est la même structure XML comme avant de le charger en arrière dans la liste déroulante, mais je n'ai pas encore trouvé un moyen d'obtenir le deuxième arbre d'éléments rempli avec les données correctes. Je pense utiliser un paramètre ou une variable pour sauvegarder l'index d'un nœud dans le premier arbre des items et trouver le nœud correspondant dans le second arbre des items, mais comment?

<?xml version="1.0" encoding="UTF-8"?> 
<field name="DropDownList" xmlns="http://www.xfa.org/schema/xfa-form/2.8/"> 
    <items xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
     <text>Lorem Ipsum 0100</text> 
     <text>Lorem Ipsum 0110</text> 
     <text>Lorem Ipsum 0120</text> 
     <text>Lorem Ipsum 0130</text> 
     <text>Lorem Ipsum 0140</text> 
    </items> 
    <items save="1" presence="hidden" xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
     <text>item5</text> 
     <text>item6</text> 
     <text>item7</text> 
     <text>item8</text> 
     <text>item9</text> 
    </items> 
</field> 

Répondre

1

Un moyen facile de faire est d'utiliser le mode sur vos modèles et apply-templates. Donc, ajoutez l'attribut mode aux apply-templates. Et ajoutez l'attribut mode avec le même nom aux modèles que vous ciblez avec les modèles d'application. Ensuite, pour la deuxième sortie, utilisez un mode différent ou laissez-le passer sans le mode.

0

Merci de votre participation. J'ai fait une autre feuille de style qui fait déjà ce que je cherche. Mais, je ne pense pas que cette solution idéale parce que je dois vérifier tous les noeuds sous les premiers éléments d'arbres deux fois ...

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xfa="http://www.xfa.org/schema/xfa-form/2.8/" xml:space="preserve"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" standalone="yes"/> 
    <xsl:variable name="filterText" select="01"/> 
    <!--Filter display items--> 
    <xsl:template match="//*[local-name()='items'][1]/*[local-name()='text']" mode="filterDisplayItems"> 
     <xsl:if test="contains(., $filterText)"> 
      <xsl:copy-of select="."/> 
     </xsl:if> 
    </xsl:template> 
    <!--Filter save items--> 
    <xsl:template match="//*[local-name()='items'][1]/*[local-name()='text']" mode="filterSaveItems"> 
     <xsl:param name="nodeIndex" select="position()"/> 
     <xsl:if test="contains(., $filterText)"> 
      <xsl:copy-of select="//*[local-name()='items'][2]/*[local-name()='text'][$nodeIndex]"/> 
     </xsl:if> 
    </xsl:template> 
    <xsl:template match="/"> 
     <field name="ListBackup"> 
      <!--Create filtered list of display items--> 
      <items xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
       <xsl:apply-templates select="//*[local-name()='items'][1]/*[local-name()='text']" mode="filterDisplayItems"/> 
      </items> 
      <!--Create filtered list of save items--> 
      <items save="1" presence="hidden" xmlns="http://www.xfa.org/schema/xfa-template/3.6/"> 
       <xsl:apply-templates select="//*[local-name()='items'][1]/*[local-name()='text']" mode="filterSaveItems"/> 
      </items> 
     </field> 
    </xsl:template> 
</xsl:stylesheet> 

... ce qui provoque un retard de performance à mes yeux. Il doit y avoir un meilleur moyen. Lorsque le modèle qui filtre le premier arbre d'éléments trouve une correspondance, vous obtenez facilement son index avec ... select = "position()". Cela devrait passer au modèle qui filtre l'arbre des deuxièmes éléments. Il vous suffit alors de copier les nœuds par là indices. Des idées comment accompagner cela?