XSL模板使加载速度非常慢

时间:2017-09-17 02:19:12

标签: javascript xml performance xslt xpath

您好以下代码使我的页面加载速度非常慢。你能帮忙吗?

 <xsl:template match="Category" mode="CategorySelectorScript">
            <xsl:variable name="ThisCategoryID" select="CategoryID"/>
            <xsl:variable name="HasChildren"><xsl:choose>
                <xsl:when test="../Category[ParentCategoryID=$ThisCategoryID]">
                    true
                </xsl:when>
                <xsl:otherwise>
                    false
                </xsl:otherwise></xsl:choose>
            </xsl:variable>
            arrCategory=new Array(<xsl:value-of select="CategoryID"/>, <xsl:value-of select="ParentCategoryID"/>, '<xsl:value-of select="Name"/>', <xsl:value-of select="$HasChildren"/>);
            arrCategories.push(arrCategory);
        </xsl:template>

问题出在这一行<xsl:when test="../Category[ParentCategoryID=$ThisCategoryID]">当我从XPath中删除../时,它加载速度很快,但后来我没有获得工作功能。那么有../的替代方案吗?

完整代码

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"    
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="xsl">

<xsl:output method="xml" 
            omit-xml-declaration="yes"
            indent="yes"
            encoding="utf-8"/>

    <xsl:template match="Location">
        <xsl:call-template name="CategorySelectorScript"/>

        <form id="frmLocationCategoryAdd" action="locationcategoriesadd.php" method="post">
            <div>
                <input type="hidden" id="inpAction" name="inpAction" value="SAVE"/>
                <input type="hidden" id="inpLocationID" name="inpLocationID" value="{LocationID}"/>
                <input type="hidden" name="inpCategoryIDs" id="inpCategoryIDs" value=""/>
            </div>

            <div id="categoryselects"><xsl:text> </xsl:text></div>

            <div><a id="categoryselected" href="#" class="actionlink addcategory">Add this category</a></div>
            <div id="categoryalreadyselected">This category has already been selected</div>

            <h3 id="categoriestoadd">Categories to add</h3>
            <div id="categoriesselected"><p id="nocategoriesmessage">No categories</p></div>

            <div class="formcontrols">
                <a class="savelink" href="#" id="savelink">
                    <span>Add Categories</span>
                </a>
                <a class="cancellink" href="#" id="cancellink">
                    <span>Cancel</span>
                </a>
            </div>
        </form>
    </xsl:template>


    <xsl:template name="CategorySelectorScript">
        <script type="text/javascript">
        <xsl:value-of select="$start_html_comment" disable-output-escaping="yes"/>
            $(document).ready(
            function()
            {
                $('#cancellink').click( function() {
                    $('#inpAction').val('CANCEL');
                    $('#frmLocationCategoryAdd').submit();
                    }
                );

                $('#savelink').click( function() {
                    ProcessCategoryIDs();

                    <!-- alert($('#inpCategoryIDs').val()); -->

                    $('#frmLocationCategoryAdd').submit();
                }
                );

                $('#categoryselects').append(CreateCategorySelectBox(<xsl:value-of select="/XML/RootCategoryID"/>));

                $('#categoryselected').hide();
                $('#categoryalreadyselected').hide();

                $('#categoryselected').click( function() {
                    $('#categoryselected').hide();
                    $('#nocategoriesmessage').hide();

                    intThisCategoryID=0;
                    strCategoryHierarchy='';
                    $('#categoryselects').children().each( function(i) {
                        if (!isNaN(parseInt(this.value, 10)))
                        {
                            intThisCategoryID=parseInt(this.value, 10);
                            strCategoryHierarchy+=GetCategoryName(intThisCategoryID)+' <xsl:value-of select="'&gt;'" disable-output-escaping="yes"/> ';
                        }
                    }
                    );

                    <!-- alert(intThisCategoryID); -->

                    <!-- remove last > -->
                    strCategoryHierarchy=strCategoryHierarchy.replace(/ <xsl:value-of select="'&gt;'" disable-output-escaping="yes"/> $/i, '');

                    strCategoryToAdd='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>div id="AddedCategory_'+intThisCategoryID+'" class="addedcategory"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                    strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>span class="addedcategoryhierarchy"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>'+strCategoryHierarchy+'<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/span<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                    strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>a id="DeleteCategory_'+intThisCategoryID+'" class="actionlink deletecategory" onclick="DeleteCategory(this)"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>Delete this category<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/a<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                    strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/div<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                    $('#categoriesselected').append(strCategoryToAdd);

                    return false;   
                }
                );

            }
            )

            function DeleteCategory(oDeleteClicked)
            {
                $('#AddedCategory_'+getID(oDeleteClicked.id)).remove();

                if (0==$('.addedcategory').length)
                    $('#nocategoriesmessage').show();
            }

            function GetCategoryName(intCategoryID)
            {
                for (i=0; i<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>arrCategories.length; i++)
                {
                    if (arrCategories[i][0]==intCategoryID)
                        return arrCategories[i][2];
                }

                return '';
            }

            function SelectClicked(oSelect)
            {           
                intCategoryID=$('#'+oSelect.id).val();
                intParentCategoryID=getID(oSelect.id);
                strCategoryText=$('#CategoryID_'+intParentCategoryID+'_'+intCategoryID).html();
                CategoryClicked(intCategoryID, intParentCategoryID, strCategoryText);
            }

            function CategoryClicked(intCategoryID, intParentCategoryID, strCategoryText)
            {
                    <!--
                    alert('intCategoryID: '+intCategoryID);
                    alert('intParentCategoryID: '+intParentCategoryID);
                    -->

                    $('#categoryselected').hide();
                    $('#categoryalreadyselected').hide();
                    <!-- some pretty gnarly stuff to get all sibling select boxes after the current one -->
                    var allSelects = $('#categoryselects select');
                    var currentIndex = allSelects.index($('#CategorySelect_'+intParentCategoryID)[0]);
                    var nextSiblings = allSelects.gt(currentIndex);
                    nextSiblings.remove();

                    <!-- if this isn't a leaf category, populate the next select box with its children -->
                    if (-1!=strCategoryText.search('&gt;') || -1!=strCategoryText.search('<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>')) <!-- for some reason safari sees the non-escaped > in the string -->
                    {
                        $('#categoryselects').append(CreateCategorySelectBox(intCategoryID));
                        $('#CategorySelect_'+intCategoryID).focus();

                        /* force scrolling div over to the right */
                        oCategorySelects=document.getElementById('categoryselects');
                        oCategorySelects.scrollLeft=oCategorySelects.scrollWidth-680;
                    }
                    else
                    {
                        /* check that this category isn't already in the selected categories */
                        var bFound=false;

                        $('#categoriesselected').children().each( function() {
                            if (getID(this.id)==intCategoryID)
                                bFound=true;
                        }
                        );

                        if (bFound)
                            $('#categoryalreadyselected').show();
                        else
                            $('#categoryselected').show();
                    }
            }

            function ProcessCategoryIDs()
            {
                arrCategoryIDs=new Array();

                $('#categoriesselected').children().each( function() {
                    if (!isNaN(parseInt(getID(this.id), 10)))
                        arrCategoryIDs.push(getID(this.id));
                }
                );

                $('#inpCategoryIDs').val(arrCategoryIDs.join());
            }

            <!-- generate javascript array from the categories XML: -->
            var arrCategories=new Array();

            <xsl:apply-templates select="/XML/Categories/Category" mode="CategorySelectorScript"/>

            <!-- alert(dump(arrCategories)); -->

            <!-- category select box writing stuff -->
            function CreateCategorySelectBox(intCategoryID)
            {
                strSelectBox='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>select id="CategorySelect_'+intCategoryID+'" size="10" onclick="SelectClicked(this)"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                arrCategoriesInThisCategory=GetCategoriesWithParentID(intCategoryID);

                for (i=0; i<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>arrCategoriesInThisCategory.length; i++)
                {
                    if (true==arrCategoriesInThisCategory[i][3])
                        strChildMarker=' <xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';
                    else
                        strChildMarker='';

                    strSelectBox+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>option id="CategoryID_'+intCategoryID+'_'+arrCategoriesInThisCategory[i][0]+'" value="'+arrCategoriesInThisCategory[i][0]+'"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>'+arrCategoriesInThisCategory[i][2]+strChildMarker+'<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/option<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';
                }

                strSelectBox+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/select<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                return strSelectBox;
            }

            function GetCategoriesWithParentID(intParentCategoryID)
            {
                arrResult=new Array();
                for (i=0; i<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>arrCategories.length; i++)
                {
                    if (arrCategories[i][1]==intParentCategoryID)
                        arrResult.push(arrCategories[i]);
                }

                return arrResult;
            }
        // <xsl:value-of select="$end_html_comment" disable-output-escaping="yes"/>
        </script>
    </xsl:template>

    <xsl:template match="Category" mode="CategorySelectorScript">
        <xsl:variable name="ThisCategoryID" select="CategoryID"/>
        <xsl:variable name="HasChildren"><xsl:choose>
            <xsl:when test="../Category[ParentCategoryID=$ThisCategoryID]">
                true
            </xsl:when>
            <xsl:otherwise>
                false
            </xsl:otherwise></xsl:choose>
        </xsl:variable>
        arrCategory=new Array(<xsl:value-of select="CategoryID"/>, <xsl:value-of select="ParentCategoryID"/>, '<xsl:value-of select="Name"/>', <xsl:value-of select="$HasChildren"/>);
        arrCategories.push(arrCategory);
    </xsl:template>

    <!-- category filter for location searches (front and back end ) -->
    <xsl:template name="CategoryFilter">
        <xsl:param name="FiltersOpen">0</xsl:param>

        <input type="hidden" name="inpCategoryIDs" id="inpCategoryIDs" value="0"/>

        <xsl:choose>
            <xsl:when test="0 = $FiltersOpen">
                <a href="#" id="filterlink">Filter by location categories</a>
                <a href="#" id="cancelfilterlink" style="display:none">Remove location category filters</a>
            </xsl:when>
            <xsl:otherwise>
                <a href="#" id="filterlink" style="display:none">Filter by location categories</a>
                <a href="#" id="cancelfilterlink">Remove location category filters</a>
            </xsl:otherwise>
        </xsl:choose>

        <div id="categoryfilters">
            <xsl:if test="0 = $FiltersOpen">
                <xsl:attribute name="style">display:none;</xsl:attribute>
            </xsl:if>
            <div id="categoryselects"><xsl:text> </xsl:text></div>

            <a id="categoryselected" href="#" class="actionlink addcategory">Add this category</a>
            <div id="categoryalreadyselected">This category has already been selected</div>

            <h3 id="categoriestoadd">Categories to filter by</h3>
            <div id="categoriesselected"><p id="nocategoriesmessage">No categories</p></div>
        </div> <!-- #categoryfilters -->

        <script type="text/javascript">
        <xsl:value-of select="$start_html_comment" disable-output-escaping="yes"/>
            $(document).ready(
                function()
                {
                    $('#filterlink').click( function () {
                        $('#categoryfilters').slideDown();
                        $(this).hide();
                        $('#cancelfilterlink').show();
                        return false;
                    }
                    );

                    $('#cancelfilterlink').click( function() {
                        $('#categoryfilters').slideUp();

                        $('#categoryfilters select:gt(0)').remove();
                        $('#categoryfilters select:first option[@selected]').removeAttr('selected');

                        $('#categoriesselected').children().remove();
                        $('#categoriesselected').append('<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>p id="nocategoriesmessage"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>No categories<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/p<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>')

                        $(this).hide();
                        $('#filterlink').show();

                        return false;
                    }
                    );

                    if (0!=arrSelectedCategoryIDs.length)
                    {
                        $('#nocategoriesmessage').hide();
                        $('#categoryfilters').show();
                        $('#filterlink').hide();
                        $('#cancelfilterlink').show();

                        for (i=0; i<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>arrSelectedCategoryIDs.length; i++)
                        {
                            SelectCategory(arrSelectedCategoryIDs[i]);
                        }
                    }
                }
            );

            function SelectCategory(intCategoryID)
            {
                strCategoryToAdd='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>div id="AddedCategory_'+intCategoryID+'" class="addedcategory"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>span class="addedcategoryhierarchy"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>'+CategoryHierarchyString(intCategoryID)+'<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/span<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>a id="DeleteCategory_'+intCategoryID+'" class="actionlink deletecategory" onclick="DeleteCategory(this)"<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>Delete this category<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/a<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                strCategoryToAdd+='<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>/div<xsl:value-of select="'&gt;'" disable-output-escaping="yes"/>';

                $('#categoriesselected').append(strCategoryToAdd);
            }

            function CategoryHierarchyString(intCategoryID)
            {
                var strTemp='';
                var i=0;

                for (i=0; i<xsl:value-of select="'&lt;'" disable-output-escaping="yes"/>arrCategories.length; i++)
                {
                    if (arrCategories[i][0]==intCategoryID)
                    {
                        if (<xsl:value-of select="/XML/RootCategoryID"/>==arrCategories[i][1])
                        {
                            return arrCategories[i][2];
                        }
                        else
                        {
                            strTemp=arrCategories[i][2];
                            return CategoryHierarchyString(arrCategories[i][1])+' <xsl:value-of select="'&gt;'" disable-output-escaping="yes"/> '+strTemp;
                        }
                    }
                }
            }
        // <xsl:value-of select="$end_html_comment" disable-output-escaping="yes"/>
        </script>
    </xsl:template>

</xsl:stylesheet>

PS:如果还有其他需要,请发表评论我将与您分享要求。

由于

1 个答案:

答案 0 :(得分:0)

您尚未显示源XML。

如果Category元素的数量很大,并且它们在文档中都处于同一级别,那么您应该通过定义键来获得改进:

<xsl:key name="CategoryByParentCategory" match="Category"
     use="ParentCategoryID"/>

然后将测试从test="../Category[ParentCategoryID=$ThisCategoryID]"更改为test="key('CategoryByParentCategory', $ThisCategoryID)"

(如果嵌套Category元素或者您没有搜索所有元素,则此更改不安全:这就是我们需要查看XML的原因

关于你的逻辑的观点:你正在将变量$HasChildren的值设置为包含字符串“true”或“false”的文本节点,该字符串由空格加载包围,然后将其插入到某些空格中生成Javascript。通过将变量声明更改为

,可以更方便地实现效果
<xsl:variable name="HasChildren"
 select="boolean(key('CategoryByParentCategory', $ThisCategoryID))"/>