根据子节点中的值选择父/祖先节点

时间:2010-08-10 13:23:05

标签: javascript xslt

我公司制作出版物,输出客户当前的图表集, 您可以在发布中搜索具有给定属性值的图表。

只有当值包含在第一个Attribute节点中时才有效。

我和另一个人一直试图修复它,以便搜索所有属性。

以下是用于搜索属性的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,它查看needle参数中作为用户输入的搜索词的子字符串是否存在于haystack参数内,该参数是用户搜索发布的元素或属性的值。我自己不确定究竟发生了什么,但它似乎正常工作。

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>

        

如果第一个属性元素的Value子元素中存在Draft,则当前xsl将呈现图表的链接。但是搜索PMO将不会返回任何内容。

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

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

感谢。

2 个答案:

答案 0 :(得分: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>

Whit param pKeywords默认值设置为'Draft',输出:

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

注意:当param pKeywords未设置或设置为空字符串''输出param pAttributes中设置的所有节点时,您可以认为关于此模板作为过滤器。此外,您可以编辑输出以使其对您的逻辑有用,例如:您可以输出非空pAttributes的测试值,声明一个变量,其中包含调用此模板的内容,测试字符串值如下变量并将样板应用于样式表片段中。

答案 1 :(得分: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文件,以便搜索到的内容。

在描述搜索中找到某些内容时,选择“发布节点”以在渲染中使用。 由于有多个Attribute节点与Description描述相同,因此只搜索第一个Attribute元素。因此,使用for-each将遍历所有属性,但同时将上下文更改为要搜索的xml文件。

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