如何在Silverlight中使用XSLT格式化并输出XML文档
在.NET中,使用XslCompliedTransform可以非常方便地使用XSLT对XML文档进行格式化,
// Load XML Document XPathDocument xmlXPathDoc = new XPathDocument(HttpContext.Current.Server.MapPath("sample.xml"); // Load XSLT Document XslCompiledTransform xslTransform = new XslCompiledTransform(); // Add parameters to XSLT Document (optional) XsltArgumentList xslArg = new XsltArgumentList(); xslArg.AddParam("param1", string.Empty, "value1"); xslArg.AddParam("param2", string.Empty, "value2"); // Output TextWriter writer = new StringWriter(); xslTransform.Transform(xmlXPathDoc, xslArg, writer); Response.Write(writer.ToString());
但是在Silverlight中我们却无法使用XslCompiledTransform以及XsltTransform对象,有两个方法可以解决该问题:
1. 将XslCompiledTransform相关代码移到Web Service中,然后在Silverlight中异步调用Web Service。
2. 借用浏览器进行解析。
第一种方法实现起来比较简单,无非就是将.NET代码放到Web Service中,然后在Silverlight中调用。但是这种方法有一定的局限性,例如需要在服务器上进行额外的部署,访问安全性以及权限等问题。第二种方法是借用浏览器的ActiveX代替XslCompiledTransform来解析XML文档,代码由Javascript完成,然后在Silverlight中调用。不足之处就是需要做浏览器类型判断,然后采用不同的方式进行解析。下面的代码用于说明如何在IE浏览器中调用ActiveX解析XML文档,并在Silverlight中使用。
HtmlPage.Window.Eval(@ "function transform(xml, xsl) { var xmlDOM = new ActiveXObject("MSXML2.DOMDocument.6.0"); xmlDOM.LoadXML(xml); var xslDOM = new ActiveObject("MSXML2.DOMDocument.6.0"); xslDOM.LoadXML(xsl); return xmlDOM.transformNode(xslDOM); }");
在Silverlight中使用的时候只需要将XML文档和XSLT文档的内容以字符串形式传递进来就行了,
string result = HtmlPage.Window.Invoke("transform", xmlString, xslString) as string;
如何需要给XSLT文档传递参数怎么办呢?看下面的代码,我们同时将该功能封装成一个类。
public class XsltTransformProxy { private const string SCRIPT = "function transform(xml, xsl)" + " {{" + " var xmlDoc = new ActiveXObject(\"MSXML2.DOMDocument.6.0\");" + " xmlDoc.async = false;" + " xmlDoc.loadXML(xml);" + " var xslDoc = new ActiveXObject(\"MSXML2.FreeThreadedDOMDocument.6.0\");" + " xslDoc.async = false;" + " xslDoc.loadXML(xsl);" + " var xslt = new ActiveXObject(\"MSXML2.XSLTemplate.6.0\");" + " xslt.stylesheet = xslDoc;" + " var xslproc = xslt.createProcessor();" + " xslproc.input = xmlDoc;" + " {0}" + " xslproc.transform();" + " return xslproc.output;" + " }}"; private List<XslParameter> xslArgumentList; public XElement XslDocument { get; set; } public XElement XmlDocument { get; set; } public void AddParam(string name, string param) { if (xslArgumentList == null) { xslArgumentList = new List<XslParameter>(); } xslArgumentList.Add(new XslParameter(name, param)); } public XElement Transform() { StringBuilder scriptBuilder = new StringBuilder(); if (this.xslArgumentList != null && this.xslArgumentList.Count > 0) { foreach (XslParameter param in this.xslArgumentList) { scriptBuilder.Append("xslproc.addParameter(\"" + param.Name + "\", \"" + param.Parameter + "\");"); } } HtmlPage.Window.Eval(string.Format(SCRIPT, scriptBuilder.ToString())); return XElement.Parse(HtmlPage.Window.Invoke("transform", XmlDocument.ToString(), XslDocument.ToString()) as string); } } public class XslParameter { private string name; public string Name { get { return name; } set { name = value; } } private string parameter; public string Parameter { get { return parameter; } set { parameter = value; } } public XslParameter() { } public XslParameter(string _name, string _parameter) { this.name = _name; this.parameter = _parameter; } }
来看一下如何调用:
XElement xElement = new XElement("Items"); xElement.Add(new XElement("Item", "aa", new XAttribute("Id", "0"))); xElement.Add(new XElement("Item", "bb", new XAttribute("Id", "1"))); XsltTransformProxy transformProxy = new XsltTransformProxy(); transformProxy.XmlDocument = xElement; transformProxy.AddParam("param1", "p1"); transformProxy.AddParam("param2", "p2"); transformProxy.XslDocument = XElement.Load(new Uri("sample.xslt", UriKind.Relative).ToString()); xmlDocument = transformProxy.Transform();
当然,其中注入到页面上的Javascript代码需要优化以支持多浏览器。使用该方法可以弥补在Silverlight中无法使用XslCompiledTransform以及XsltTransform对象进行XML文档的解析。
参考文档:http://msdn.microsoft.com/en-us/library/windows/desktop/ms763679(v=vs.85).aspx