65.9K
CodeProject 正在变化。 阅读更多。
Home

使用带参数的 XSL 处理 XML

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (2投票s)

2012年3月28日

CPOL

4分钟阅读

viewsIcon

29874

将参数传递给 XSL

引言

最近,在为一个 Web 应用程序开发综合报告时,我们使用 XML/XSL 处理来生成报告,该报告基本上是一个通过 XSL 处理生成的自定义网格。用户界面的截图在概述部分给出。

该报告是使用通过 XML 数据通过 XSL 生成的自定义网格设计的。 该报告基本上显示每日、MTD 和年度的综合数据。 XML 输出包含给定交易日期的每日、MTD 和 YTD 的数据。 因此,问题是在用户在 UI 中选择每日/MTD/年度时,如何从 XML 中提取相应的数据。

像往常一样,最初的想法是使用三个 XSL 来处理每日、每月和每年。 但在展望未来时,对可维护性和代码重复的考虑让我寻找更可靠的解决方案。 让我们看看我们是如何实现解决方案的。

概述

不深入研究网格是如何开发的细节; 只关注问题,让我们看看需求的简要说明。

为了更好地理解,让我们看一下报告屏幕。 用户从屏幕上选择报告类型(值将为“D”、“Y”、“M”),然后单击“应用”按钮; 根据用户的选择,需要提取和处理 XML 数据。

例如,在报告屏幕中,报告标题是需要提取的 XML 元素之一,该元素对应于用户选择的报告类型。 当用户从报告类型中选择“Daily”时,XSL 处理器需要从 XML 中提取 XPATHroot/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 处理,并将其应用于各种应用程序。

© . All rights reserved.