2010-08-10 154 views
0

我的公司制作出版物输出客户端当前的一组图表, 您可以在出版物中搜索具有给定属性值的图表。根据子节点中的值选择父/祖先节点

这个工作,但只有当该值包含在第一个属性节点。

我和另一位同事一直在试图修复它,以便它搜索所有属性。

这是用于搜索属性的xsl代码片段。它正在查看文件夹图形和图形元素,以查看子元素元素是否包含用户输入的单词。

 <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> 

这里是Javascript函数containsKeyword它查看是否在针参数,该参数是由用户输入的检索词的字符串存在草堆参数,它是一个元素的值或属性用户是内部搜索出版物。我自己不确定究竟发生了什么,但它看起来工作正常。

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; 
    } 

正在搜索的xml。

<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> 

目前XSL将呈现的链接图,如果草案进入,因为它的第一属性元素的值的子元素存在。但是搜索PMO将不会返回任何内容。

问题是,当需要查看CustomAttribute元素中的所有子元素时,xsl只会查看第一个Attribute元素。

我们尝试使用for-each来遍历遍历xml树时遇到问题的所有Attribute元素以获取Diagram祖先,以便可以为渲染选择它。

谢谢。

+0

这个问题绝对不清楚。我看不到XSLT代码在做什么(你只是显示了很小一部分代码),并且不清楚你想实现什么。此外,还不清楚JS代码是否与您的问题有关,或者不是。不要指望监视和回答xslt问题的人善于处理JS - 因此如果JS很重要,至少应该用文字说明JS代码正在做什么。总之,请重做你的问题。 – 2010-08-10 14:00:48

+0

我会说你的'js:containsKeywords($ objXML/*/CustomAttributes/Attribute/Value,$ searchKeywords)'函数不能像你认为的那样工作,或者至少这是我会看的地方,但是作为Dimitre说,没有办法告诉,因为这是不包括 – Woody 2010-08-10 15:06:51

+0

我已经添加了JavaScript回来,我希望这使得它更清晰或有助于消除可能的错误来源。 – ywm 2010-08-10 15:21:36

回答

0

我认为可以在XSLT中完成相同的任务。这个样式表:

<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> 

有了这个正确输入:设置为 '草稿'

<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> 

白衣PARAM pKeywords默认值,输出:

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

注意:当PARAM pKeywords是未设置或设置为空字符串''输出参数中设置的所有节点pAttributes,s你可以把这个模板想象成一个过滤器。另外,您可以编辑输出以使其对您的逻辑有用,例如:您可以输出非空的测试值pAttributes,使用调用此模板的内容声明变量,测试此变量的字符串值以及像样式表片段一样应用模板。

+0

我将如何能够使用您的代码返回根节点? 图表分散在单独的xml文件中,xsl搜索每个文件,然后将当前的xml文件发送到渲染模板。 – ywm 2010-08-11 11:17:33

+0

@ywm:这个命名模板是扩展函数的XSLT实现(扩展很慢,每次调用都会加载脚本引擎)。您可以将要搜索的节点集(param'pAttributes')和空格分隔的关键字列表(参数'pKeywords')。输出可能只是一个虚拟的字符串,用于测试(就像你在'test =“js:containsKeywords(...')中那样,你”存储“了一个变量。 – 2010-08-11 13:16:23

0

好吧,我已经找出了问题所在。

这里是解决方案,我会尝试解释发生了什么。

<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> 

这段代码是一个模板的一部分,该模板应用于所有不同的Xml文件中,用于搜索内容。

在描述搜索中,当找到某物时,选择发布节点以在渲染中使用。 由于存在多个属性节点,因此说明搜索将只搜索第一个属性元素。因此,使用for-each将遍历所有属性,但同时将上下文更改为正在搜索的xml文件。

因此,为了将正确的位发送到渲染模板,我在源变量中的for-each之前保存了上下文,并且当我找到匹配时,我将源变量发送给渲染。

相关问题