2010-08-10 6 views
0

Mon entreprise crée une publication qui génère un ensemble de diagrammes courant pour les clients, Vous pouvez rechercher des diagrammes avec une valeur d'attribut donnée dans la publication.Sélection du nœud parent/ancêtre en fonction de la valeur du nœud enfant

Cela fonctionne uniquement si la valeur est contenue dans le premier noeud Attribut.

Moi et un autre camarade essayons de le réparer afin qu'il recherche tous les attributs.

Voici l'extrait xsl utilisé pour rechercher les attributs. Il regarde dans le diagramme de dossier et les éléments de forme pour voir si un élément d'attribut d'enfant contient un mot entré par l'utilisateur.

 <xsl:template name="testObject"> 
    <xsl:if test="(name() = 'Shape' and $includeShapes) or (name() = 'Folder' and $includeFolders) or (name() = 'Document' and $includeDocuments) or (name() = 'Diagram' and $includeDiagrams)"> 
     <xsl:variable name="objXMLLocation"> 
      <xsl:choose> 
       <xsl:when test="name() = 'Folder'"> 
        <xsl:value-of select="concat(@ID, '/folder.xml')" /> 
       </xsl:when> 
       <xsl:when test="name() = 'Document'"> 
        <xsl:value-of select="concat(@ID, '/document.xml')" /> 
       </xsl:when> 
       <xsl:when test="name() = 'Diagram'"> 
        <xsl:value-of select="concat(@ID, '/diagram.xml')" /> 
       </xsl:when> 
       <xsl:when test="name() = 'Shape'"> 
        <xsl:value-of select="concat(../../@ID, '/', ../../@ID, '_files/', @Source)" /> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:if test="js:fileExists($objXMLLocation)"> 
      <xsl:variable name="objXML" select="document($objXMLLocation)" /> 
      <xsl:choose> 
       <xsl:when test="$searchName"> 
        <xsl:if test="js:containsKeywords($objXML/*/Properties/RepositoryName, $searchKeywords)"> 
         <xsl:apply-templates mode="render" select="."> 
          <xsl:with-param name="fullXML" select="$objXML" /> 
         </xsl:apply-templates> 
        </xsl:if> 
       </xsl:when> 
       <xsl:when test="$searchDescription"> 
        <xsl:if test="js:containsKeywords($objXML/*/Properties/Description, $searchKeywords)"> 
         <xsl:apply-templates mode="render" select="."> 
          <xsl:with-param name="fullXML" select="$objXML" /> 
         </xsl:apply-templates> 
        </xsl:if> 
       </xsl:when> 
       <xsl:when test="$searchAttributes"> 
        <xsl:if test="name() != 'Folder'">      
        <xsl:if test="js:containsKeywords($objXML/*/CustomAttributes/Attribute/Value,$searchKeywords)"> 
         <xsl:apply-templates mode="render" select="."> 
          <xsl:with-param name="fullXML" select="$objXML" /> 
         </xsl:apply-templates> 
        </xsl:if> 
        </xsl:if> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:if> 
    </xsl:if> 
</xsl:template> 

Voici la fonction Javascript containsKeyword il semble voir si les sous-chaînes dans le paramètre d'aiguille qui sont des mots de recherche saisis par l'utilisateur existe à l'intérieur du paramètre de botte de foin qui est la valeur d'un élément ou un attribut que l'utilisateur est recherche dans la publication pour. Je suis moi-même incertain de ce qui se passe exactement, mais cela semble fonctionner correctement.

function containsKeywords(haystack, needles) { 
     var ks = needles[0].selectNodes('//K'); 
     var n; 
     if (haystack[0].firstChild) { 
      n = haystack[0].firstChild.nodeValue.toUpperCase(); 
     } else { 
      return 0; 
     } 
     for (var i = 0; i < ks.length; i++) { 
      if (n.indexOf(ks[i].firstChild.nodeValue) < 0) { 
       return 0; 
      } 
     } 
     return 1; 
    } 

Le xml en cours de recherche.

<Diagram ID="49ab6eb5-c51f-4e36-9495-869897ef0d0d"> 
    <CustomAttributes> 
    <Attribute> 
    <Name>Approval Status</Name> 
    <Description>Document/Diagram/Object Approval Status</Description> 
    <Value>Draft - Work in Progress</Value> 
    <Datatype>Text</Datatype> 
</Attribute> 
<Attribute> 
    <Name>Next Document Review Date</Name> 
    <Description>When is this document to be reviewed next?</Description> 
    <Value /> 
    <Datatype>Date</Datatype> 
</Attribute> 
<Attribute> 
    <Name>Stakeholder View</Name> 
    <Description>Select the Stakeholder View</Description> 
    <Value>PMO</Value> 
    <Datatype>Text</Datatype> 
</Attribute> 

Le xsl actuel va rendre un lien vers le diagramme si le tirage est entrer tel qu'il existe dans l'élément enfant Valeur du 1er élément d'attribut. Mais la recherche de PMO ne retournera rien.

Le problème est que xsl ne regarde que le premier élément Attribute, lorsqu'il doit regarder tous les éléments enfants de l'élément CustomAttribute.

Nous avons essayé d'utiliser un for-each pour parcourir tous les éléments d'attributs que nous avions du mal à traverser l'arborescence xml pour obtenir l'ancêtre Diagram afin qu'il puisse être sélectionné pour le rendu.

Merci.

+0

Cette question n'est absolument pas claire. Je ne vois pas ce que fait le code XSLT (vous montrez seulement une très petite partie du code) et ce que vous voulez obtenir n'est pas clair. En outre, il n'est pas clair si le code JS a quelque chose à voir avec votre problème, ou non. Ne vous attendez pas à ce que les personnes qui surveillent et répondent aux questions xslt soient bonnes à JS - donc si JS est important, expliquez au moins avec des mots ce que fait le code JS. En bref, veuillez retravailler votre question. –

+0

Je dirais que votre fonction 'js: containsKeywords ($ objXML/*/CustomAttributes/Attribute/Value, $ searchKeywords)' ne fonctionne pas comme vous le pensez, ou du moins c'est ce que j'aurais l'air, mais comme Dimitre dit, il n'y a aucun moyen de dire que ce n'est pas inclus – Woody

+0

J'ai ajouté le javascript dans J'espère que cela le rend plus clair ou aide à éliminer les sources possibles d'erreur. – ywm

Répondre

0

Je pense que la même tâche pourrait être faite dans XSLT. Cette feuille de style:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="CustomAttributes" name="search"> 
     <xsl:param name="pAttributes" select="Attribute/Value"/> 
     <xsl:param name="pKeywords" select="''"/> 
     <xsl:choose> 
      <xsl:when test="$pKeywords != ''"> 
       <xsl:call-template name="search"> 
        <xsl:with-param name="pAttributes" 
            select="$pAttributes 
                [contains(
                 concat(' ',.,' '), 
                 concat(' ', 
                   substring-before(
                    concat($pKeywords,' '), 
                    ' '), 
                   ' '))]"/> 
        <xsl:with-param name="pKeywords" select="substring-after($pKeywords,' ')"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <found> 
        <xsl:copy-of select="$pAttributes"/> 
       </found> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Avec cette entrée appropriée:

<Diagram ID="49ab6eb5-c51f-4e36-9495-869897ef0d0d"> 
    <CustomAttributes> 
     <Attribute> 
      <Name>Approval Status</Name> 
      <Description>Document/Diagram/Object Approval Status</Description> 
      <Value>Draft - Work in Progress</Value> 
      <Datatype>Text</Datatype> 
     </Attribute> 
     <Attribute> 
      <Name>Next Document Review Date</Name> 
      <Description>When is this document to be reviewed next?</Description> 
      <Value /> 
      <Datatype>Date</Datatype> 
     </Attribute> 
     <Attribute> 
      <Name>Stakeholder View</Name> 
      <Description>Select the Stakeholder View</Description> 
      <Value>PMO</Value> 
      <Datatype>Text</Datatype> 
     </Attribute> 
    </CustomAttributes> 
</Diagram> 

Whit param pKeywords valeur par défaut réglée sur 'Projet', sortie:

<found> 
    <Value>Draft - Work in Progress</Value> 
</found> 

Remarque: Lorsque param pKeywords est non défini ou est défini sur chaîne vide '' sortie tout le nœud défini dans param pAttributes, s o vous pouvez penser à ce modèle comme un filtre. Aussi, vous pouvez éditer la sortie pour la rendre utile pour votre logique, par exemple: vous pouvez simplement sortir la valeur de test pour pAttributes non vide, déclarer une variable avec le contenu de l'appel de ce modèle, tester la valeur de chaîne de cette variable appliquez les modèles comme dans votre fragment de feuille de style.

+0

Comment serais-je en mesure de retourner le nœud racine en utilisant votre code? Les diagrammes sont répartis sur des fichiers xml séparés et le xsl les recherche chacun, puis le fichier xml actuel est envoyé au modèle de rendu. – ywm

+0

@ywm: ce modèle nommé est une implémentation XSLT de votre fonction d'extension (les extensions sont lentes, le moteur de script est chargé à chaque appel). Vous pouvez passer l'ensemble des nœuds à rechercher dans (param 'pAttributes'), et une liste séparée de mots-clés (param' pKeywords'). La sortie peut être juste une chaîne fictive pour le test (comme vous le faites dans 'test =" js: containsKeywords (... ') que vous" stockez "dans une variable. –

0

Okay J'ai compris quel était le problème.

Voici la solution que je vais essayer d'expliquer ce qui se passe.

<xsl:when test="$searchDescription"> 
        <xsl:if test="js:containsKeywords($objXML/*/Properties/Description, $searchKeywords)"> 
         <xsl:apply-templates mode="render" select="."> 
          <xsl:with-param name="fullXML" select="$objXML" /> 
         </xsl:apply-templates> 
        </xsl:if> 
       </xsl:when> 
       <xsl:when test="$searchAttributes"> 
        <xsl:variable name="source" select="."></xsl:variable> 
        <xsl:if test="name() != 'Folder'"> 
         <xsl:for-each select="$objXML/*/CustomAttributes//Attribute"> 
          <xsl:if test="js:containsKeywords(./Value,$searchKeywords)"> 
           <xsl:apply-templates mode="render" select="$source"> 
            <xsl:with-param name="fullXML" select="$objXML" /> 
           </xsl:apply-templates> 
          </xsl:if> 
         </xsl:for-each> 
        </xsl:if> 
       </xsl:when> 

Cet extrait fait partie d'un modèle qui est appliqué dans l'ensemble un fichier Xml différent de ce qui est recherché.

Dans la recherche de description lorsque quelque chose est trouvé, le nœud de publication est sélectionné pour être utilisé dans le rendu. Puisqu'il existe plusieurs nœuds d'attribut faisant la même chose que la recherche de description, le premier élément d'attribut sera recherché. Donc, l'utilisation d'un for-each passera par tous les attributs mais changera en même temps le contexte du fichier xml recherché. Donc, pour envoyer le bit correct au template de rendu, j'ai sauvegardé le contexte avant le for-each dans la variable source et quand je trouve une correspondance, j'envoie la variable source au rendu à la place.

Questions connexes