首页 > 解决方案 > c# xslt 对大 xml 字符串的转换导致 aspx 超时

问题描述

我正在使用 .NET 框架 4.5 处理一个较旧的项目。有一个带有 OnSelectedIndexChanged 事件的 aspx 页面,该事件通过服务器端调用完成。服务器端调用使用返回 xml 的存储过程,然后使用转换将 xml 转换为 html。问题是,当 xml 很大时(当前使用存储的 proc 中的 xml 格式的 10k 记录进行测试,尽管生产中的预期是 100k 记录),然后 aspx 页面超时。我不确定解决此问题的最佳方法是什么,因为 executionTimeout 的 web.config 设置设置得非常高,并且 debug 设置为 false。

网络配置

<httpRuntime maxRequestLength="102400" executionTimeout="20000"/>

ASPX 页面

<asp:DropDownList ID="ddlViews" runat="server" AutoPostBack="true" style="height:25px;min-width:150px;"  
    OnSelectedIndexChanged="ddlViews_SelectedIndexChanged">
</asp:DropDownList>

. . .

<asp:UpdatePanel ID="updPnl" runat="server">
    <Triggers> 
        <asp:AsyncPostBackTrigger ControlID="ddlViews" EventName="SelectedIndexChanged" />
     </Triggers>
    <ContentTemplate>
        <asp:Literal ID="litData" runat="server"></asp:Literal>
    </ContentTemplate>
</asp:UpdatePanel>

ASPX 代码背后

protected void ddlViews_SelectedIndexChanged(object sender, EventArgs e)
{
    if (ddlViews.Items.Count > 0 && ddlViews.SelectedValue != "-1")
    {
        System.Threading.Thread.Sleep(3000);
        ShowView();
    }
}

private void ShowView()
{
    if (ddlViews.Items.Count > 0)
    {
        string inputXml = GetXml();
        strData = Utils.ApplyXslt(inputXml);

        litData.Text = strData;
    }
}

public static string ApplyXslt(string xml)
{
    try
    {
        string xsltUri = GetXslPath();
        XsltArgumentList xslArg = new XsltArgumentList();
        xslArg.AddExtensionObject("urn:string-plus", new XslStringPlus());
        var xdoc = new XmlDocument();
        xdoc.LoadXml(xml);
        var xslt = new System.Xml.Xsl.XslCompiledTransform();

        using (var mStream = new System.IO.MemoryStream())
        {
            xslt.Load(xsltUri);
            xslt.Transform(xdoc, xslArg, mStream);
            mStream.Position = 3;
            var sr = new System.IO.StreamReader(mStream);
            return sr.ReadToEnd();
        }
    }
    catch (Exception e){
        throw new Exception(String.Format("Error Applying Xslt from path '{0}'to xml value '{1}'", xsltUri, xml) + " | " + e.StackTrace);
    }
}

对于 10k 条记录,Transform 需要近 3 分钟才能完成。如果可能的话,能够大幅减少这段时间会很棒。该页面在 1.5 分钟后超时,我找不到任何可以增加它的东西。

XSLT

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xslplus="urn:string-plus">
    <xsl:output method="html" />
    <xsl:template match="/">
        <table  id="tblLoanQuery" class="tableStyle">
            <tr>
                <xsl:for-each select="ROOT/Fields/child::*">
          <xsl:variable name="h" select="." />
                    <th><xsl:value-of select="xslplus:FormatLabel($h)" /></th>
                </xsl:for-each>
            </tr>
            <xsl:for-each select="ROOT/LoanNumbers/child::*">
                <xsl:variable name="loanId" select="." />
                <tr>
                    <xsl:for-each select="//ROOT/Fields/Field">
                        <xsl:variable name="fullFieldName" select="." />
                        <xsl:variable name="field" select="substring-after($fullFieldName,'.')" />
            <xsl:variable name="FieldValue" select="//ROOT/ROWS/row[@lqKey=$loanId]/@*[name(.)= xslplus:ConvertSpace($field)]/." />
            <td>
              <xsl:value-of select="xslplus:FormatValue($FieldValue)"/>              
            </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

标签: c#asp.netxsltxslcompiledtransform

解决方案


就 XSLT 而言,它似乎//ROOT/ROWS/row[@lqKey=$loanId]建议您使用密钥<xsl:key name="row-ref" match="ROOT/ROWS/row" use="@lqKey"/>并使用key('row-ref', $loanId)而不是//ROOT/ROWS/row[@lqKey=$loanId]. 使用密钥可能会提高运行时性能。


推荐阅读