使用带参数的 XSL 处理 XML






4.11/5 (2投票s)
将参数传递给 XSL
引言
最近,在为一个 Web 应用程序开发综合报告时,我们使用 XML/XSL 处理来生成报告,该报告基本上是一个通过 XSL 处理生成的自定义网格。用户界面的截图在概述部分给出。
该报告是使用通过 XML 数据通过 XSL 生成的自定义网格设计的。 该报告基本上显示每日、MTD 和年度的综合数据。 XML 输出包含给定交易日期的每日、MTD 和 YTD 的数据。 因此,问题是在用户在 UI 中选择每日/MTD/年度时,如何从 XML 中提取相应的数据。
像往常一样,最初的想法是使用三个 XSL 来处理每日、每月和每年。 但在展望未来时,对可维护性和代码重复的考虑让我寻找更可靠的解决方案。 让我们看看我们是如何实现解决方案的。
概述
不深入研究网格是如何开发的细节; 只关注问题,让我们看看需求的简要说明。
为了更好地理解,让我们看一下报告屏幕。 用户从屏幕上选择报告类型(值将为“D”、“Y”、“M”),然后单击“应用”按钮; 根据用户的选择,需要提取和处理 XML 数据。
例如,在报告屏幕中,报告标题是需要提取的 XML 元素之一,该元素对应于用户选择的报告类型。 当用户从报告类型中选择“Daily”时,XSL 处理器需要从 XML 中提取 XPATH
‘root/reportparameters/reportdescription/description/@view’ = ‘D’。
XML 示例
请在下面找到 XML 示例。 该解决方案需要从节点的属性值中提取 XML 数据,例如从 'root/reportparameters/reportdescription/description/@view' 中的 'view
' 提取与报告类型对应的报告标题。
这些属性的值类似于“D
”、“M
”、“Y
”,分别对应于每日、MTD、年度。
同样,对于报告数据,这需要来自 'root/datarows/datarow/amounts/@aggregation'。
解决方案 1
最简单的解决方案是使用三个 XSL,其中属性值“D
”、“M
”、“Y
”是硬编码的。 但从长远来看,这会成为可维护性的问题,并且相同的代码会在三个 XSL 中重复出现。 下面给出了三个 XSL 之一的代码片段。 XML/XSL 处理技术在解决方案 2 中进行了解释。
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<div class="controlname reportdesc" style="font-style: italic">
<xsl:for-each select ="root/reportparameters/reportdescription">
<xsl:value-of select="description[@view='D']"/>
</xsl:for-each>
</div>
<br/>
</xsl:template>
</xsl:stylesheet>
解决方案 2
最好的解决方案是使用单个 XSL,其中可以从 Web 应用程序传递参数,这可以从客户端或服务器端完成,具体取决于需求。 挑战在于我们如何从客户端处理将参数传递给 XSL,以及是否也可以从服务器端执行相同的操作?
我们将在介绍过程中解释这两种方法。
让我们快速跳转到解决方案,不确定我是解释得太多了,而不是直接给出解决方案。
从客户端进行 XML/XSL 处理
XSL 处理是通过创建 Microsoft.XMLDOM
对象来加载 XML 数据来完成的。 同样,需要从 FreeThreadedDOMDocument
创建对象来加载 XSLT。 转换是在创建的 XSLT 处理器对象上完成的; 这是通过调用上述对象的 transform
方法来完成的。
上述过程优于我们可以使用 Microsoft.XMLDOM
对象的 "transformNode
" 方法来处理 XML 的过程,因为后者不允许 XSLT 中有两个参数。
涉及的步骤是:
1. var xml = new ActiveXObject("Microsoft.XMLDOM");
2. var xslt = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
3. xml.load("data.xml");
4. xslt.load("transformxsl.xsl");
5. var processor = new ActiveXObject("Msxml2.XSLTemplate");
6. processor.stylesheet = xslt;
7. var objXSLTProc = processor.createProcessor();
8. objXSLTProc.input = xml;
9. objXSLTProc.addParameter("reporttype", GetReportType());
10. objXSLTProc.transform();
11. document.getElementById("divReportGrid").innerHTML = objXSLTProc.output;
在上面的代码中,第 3 行完成了 XML 的加载; 这也可以通过调用单独的 ASPX 页面来完成,其中响应类型为“text/xml”。
第 9 行实际执行参数传递; objXSLTProc
对象被定义为具有参数名称“reporttype
”。 使用 JavaScript 函数 GetReportType()
检索相同的值。
最后,使用 XSL 处理器输出到 DIV
标签来呈现报告。
让我们看看 XSL(为了解释,这是一个来自原始 XML 的示例)
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name ="reporttype"></xsl:param>
<xsl:template match="/">
<div class="controlname reportdesc" style="font-style: italic">
<xsl:for-each select ="root/reportparameters/reportdescription">
<xsl:value-of select="description[@view=$reporttype]"/>
</xsl:for-each>
</div>
<br/>
</xsl:template>
</xsl:stylesheet>
在上面的 XSL 中,定义了一个名为“reporttype
”的 XSL 参数。 并且使用 XPATH
处理报告标题,该 XPATH
用于链接到定义的 XSL 参数的属性“view
”。
从服务器端进行 XML/XSL 处理 (C#)
XML/XSL 处理是使用 XPathDocument
并将参数应用于 XsltArgumentList
对象来完成的。 最后,使用 XslCompiledTransform
对象在 XPathDocument
对象上进行转换。 在 XSL 处理之后,HTML 输出将在 StringWriter
对象中。
MemoryStream ms =
new MemoryStream(System.Text.Encoding.UTF8.GetBytes(//Get the XML for processing));
XPathDocument document = new XPathDocument(ms);
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(Server.MapPath(@"/XSL/Sample.xsl"));
StringWriter sw = new StringWriter();
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("reporttype", "", reportTypeParam.ToString());
transform.Transform(document, xslArg, sw);
解决方案实现
最后,应用的解决方案是使用单个 XSL 的客户端 XSL 处理。 服务器端 XML/XSL 处理应用于生成 Excel 报告。
摘要
在本文中,我试图解释可以通过哪些不同的方式来完成带参数传递的 XML/XSL 处理,并将其应用于各种应用程序。