一.本文所涉及的内容
- 本文所涉及的内容
- xslt及其应用场景
- 简单应用示例
- 转换示例:通过xslt将xml转换成html
- 基本语法应用示例:变量,循环,条件,模板(方法),参数等
- 服务器端转换方式-结合c#进行方法扩展
- 继承(导入)和重载(重定义)的应用
二.xslt及其应用场景
XSLT可扩展样式表转换语言(Extensible Stylesheet Language Transformations)是一种对XML文档进行转化的语言,它的作用相当于就是样式表(css)之于HTML文件,XSLT中的T代表英语中的“转换”(transformation)。它是XSL(Extensible stylesheet language)规范的一部分。XSLT一个比较显著的特点是数据与显示分离,数据可以根据需要的样式或者形式进行展示,转换的方式可以为分为客户端转换(需要浏览器支持xslt)和服务器端转换。
常用应用场景如下:
第一,将源xml转换成符合要求的xml、HTML。例如某企业应用接口提供的数据为较为冗余的xml,可以按需使用xslt将源xml进行精简转换成xml或者HTML,同时如果数据源变化的话,只需要对应的调整xstl转换文件即可。
第二,搜索引擎抓取的HTML解析。此类特点是该抓取的html的格式多样而且非固定,可使用xslt进行解析成标准格式再进行入库索引,如果html格式有变化,对应修改xslt模板即可。
XSLT 是如何工作的:
a)首先XML文档被读入内存当中并存储为棵结点树
b)<xsl:template match=“/”> 模板用来选择整个树的根结点
c)模板中的规则被用来进行结点的匹配从而改变XML 树的结构
d)如果还有其它模板,那么它们必须显示地从主模板中调用 如果还有其它模板,那么它们必须显示地从主模板中调用
e)XML 树中没有匹配的部分保持原来的状态不变
f)模板应用完成后,树被作为一个新的文本文档输出出来
(更多请Google XSLT)
三.简单应用示例
转换示例1.通过xslt将xml转换成html,通过浏览器转换的方式
<?xml version="1.0" encoding="UTF-8"?>
<!--客户端转换的xslt-->
<?xml-stylesheet type="text/xsl" href="XSLT_Client.xslt"?>
<books>
<book>
<title>HTML5+CSS3从入门到精通(附1DVD)</title>
<author>李东博</author>
<publisher>清华大学出出版社</publisher>
<price>42.90</price>
<year>2015</year>
</book>
<book>
<title>安全之路——Web渗透技术及实战案例解析(第2版)</title>
<author>陈小兵</author>
<publisher>电子工业出版社</publisher>
<price>84.90</price>
<year>2015-09-1</year>
</book>
</books>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:template match="/">
<xsl:variable name="paraPath" select="/books/book" ></xsl:variable>
<html>
<body>
<h2>Books List</h2>
<table border="1">
<tr bgcolor="#87CEFA">
<th align="left">Title</th>
<th align="left">author</th>
<th align="left">publisher</th>
<th align="left">price</th>
<th align="left">year</th>
</tr>
<xsl:for-each select="$paraPath">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="author"/>
</td>
<td>
<xsl:value-of select="publisher"/>
</td>
<td>
<xsl:value-of disable-output-escaping="yes" select="price"/>
</td>
<td>
<xsl:value-of select="year"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Title | author | publisher | price | year |
---|---|---|---|---|
HTML5+CSS3从入门到精通(附1DVD) | 李东博 | 清华大学出出版社 | 42.90 | 2015 |
安全之路——Web渗透技术及实战案例解析(第2版) | 陈小兵 | 电子工业出版社 | 84.90 | 2015-09-1 |
2.通过xslt将xml转化成html,通过服务器端转换的方式
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<title>HTML5+CSS3从入门到精通(附1DVD)</title>
<author>李东博</author>
<publisher>清华大学出出版社</publisher>
<price>42.90</price>
<year>2015</year>
</book>
<book id="2">
<title>安全之路——Web渗透技术及实战案例解析(第2版)</title>
<author>陈小兵</author>
<publisher>电子工业出版社</publisher>
<price>84.90</price>
<year>2015-09-1</year>
</book>
</books>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fun_c="urn:format" exclude-result-prefixes="fun_c">
<xsl:template match="/">
<!--变量-->
<xsl:variable name="paraPath" select="/books/book" ></xsl:variable>
<html>
<head>
<script type="text/javascript" language="javascript" >
var firstName = "<xsl:value-of select="$paraPath[@id='1']/title"/>";
alert(firstName);
</script>
</head>
<body>
<h2>Books List</h2>
<table border="1">
<tr bgcolor="#87CEFA">
<th align="left">Title</th>
<th align="left">author</th>
<th align="left">publisher</th>
<th align="left">price</th>
<th align="left">year</th>
</tr>
<!--模板(方法调用)-->
<xsl:call-template name="Each.Output">
<!--传参-->
<xsl:with-param name="paraPath" select="$paraPath"/>
</xsl:call-template>
</table>
</body>
</html>
</xsl:template>
<!--模板(方法定义)-->
<xsl:template name="Each.Output">
<xsl:param name="paraPath"></xsl:param>
<!--循环-->
<xsl:for-each select="$paraPath">
<!--根据属性id进行排序-->
<xsl:sort select="@id" data-type="number"/>
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="author"/>
</td>
<td>
<!--c#扩展方法SetRed(string value)调用-->
<xsl:value-of disable-output-escaping="yes" select="fun_c:SetRed(publisher)"/>
</td>
<td>
<!--内置方法,字符串合并-->
<xsl:value-of select="concat(price,'元')"/>
</td>
<td>
<xsl:value-of select="year"/>
<!--条件判断,如果值不为空为并且2015-->
<xsl:if test="year!=''and year ='2015' ">
<xsl:value-of select="'年'"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
其中,<xsl:value-of disable-output-escaping="yes" select="fun_c:SetRed(publisher)"/>这个扩展方法需要搭配后台语言定义,如果使用客户端浏览器转换,需要注释掉。
XSLT 含有超过 100 个内建的函数,XQuery 1.0、XPath 2.0 以及 XSLT 2.0 共享相同的函数库。
这些函数用于字符串值、数值、日期和时间比较、节点和 QName 操作、序列操作、逻辑值,等等。关于 XSLT 的内置函数请参数:XSLT 函数参考手册 和 XPath、XQuery 以及 XSLT 函数。
有时候内置的方法无法满足要求,那么就需要扩展方法了,例如上述的fun_c:SetRed(string value)方法。
首先xslt文件的头部xmlns:fun_c="urn:format" 定义了一个前缀 fun_c而已,也就是命名空间,没有什么特别的意义,但必须与其他用到这个前缀的地方保持一致。如果不定义这么一个命名空间的话,直接不带前缀的调用 SetRed() 函数时,默认为的命名空间是 fn,而 fn 中是不存这个函数的。
扩展函数必须为 public 的:
/// <summary>
///xslt的扩展
/// </summary>
public class XsltExt
{
/// <summary>
/// 扩展方法
/// 声明必须为public
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public string SetRed(string str)
{
return string.Format("<span style='color:red'>{0}</span>", str);
}
}
直接上转换相关代码:
/// <summary>
/// 加载xslt文件
/// </summary>
private void LoadView(string xsltPath)
{
strXsltPath = xsltPath;
if (Cache && views.Keys.Contains(strXsltPath))
{
xct = views[strXsltPath];
}
else
{
xct = new XslCompiledTransform(Debug);
var xs = new XsltSettings { EnableScript = true, EnableDocumentFunction = true };
var settings = new XmlReaderSettings { ProhibitDtd = false };
// Create the reader.
var reader = XmlReader.Create(strXsltPath, settings);
try
{
xct.Load(reader, xs, new XmlUrlResolver());
if (Cache) views.Add(strXsltPath, xct);
}
finally
{
reader.Close();
}
}
}
/// <summary>
/// 通过xslt文件转换XML
/// </summary>
/// <param name="strXmlPath">XML文件路径</param>
/// <returns></returns>
public string TransferXmlByXslt(string xsltPath, string strXmlPath)
{
LoadView(xsltPath);
string pName = "urn:format";
string className = "WebApplicationXsltDemo.XsltExt,WebApplicationDemo";
Type t = Type.GetType(className);
if (className.Contains(','))
{
className = className.Split(',')[0];
}
object objEx = t.Assembly.CreateInstance(className);
XsltArgumentList xal = new XsltArgumentList();
xal.AddExtensionObject(pName, objEx);
var fs = new MemoryStream();
var outputstring = string.Empty;
try
{
判断文件是否存在
if (File.Exists(strXmlPath) && File.Exists(strXsltPath))
{
加载xml文件
var doc = new XPathDocument(strXmlPath);
XPathNavigator nav = doc.CreateNavigator();
转换xml
xct.Transform(nav, xal, fs);
fs.Seek(0, SeekOrigin.Begin);
var stream = new StreamReader(fs);
outputstring = stream.ReadToEnd();
xct.TemporaryFiles.Delete();
}
else
{
return string.Empty;
}
}
catch (Exception ex)
{
}
finally
{
fs.Close();
fs.Dispose();
}
return outputstring;
} }
调用方法:
private ActionResult XsltTranslate()
{
string xslt = "XSLT_server.xslt";
string xml = "XMLFile.xml";
string serverpath = Server.MapPath("~");
XsltTransfer objXsltTransfer = new XsltTransfer();
<span style="font-family: Arial, Helvetica, sans-serif;">string result </span><span style="font-family: Arial, Helvetica, sans-serif;">= objXsltTransfer.TransferXmlByXslt(serverpath + xslt, serverpath + xml);</span>
Response.Write(result);
Response.End();
return new EmptyResult();
}
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--定义方法,导入后可以重写该方法-->
<xsl:template name="Each.Output">
<xsl:param name="paraPath"></xsl:param>
</xsl:template>
</xsl:stylesheet>
XSLT_Global.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- 全局变量定义,也可以重写此变量 -->
<xsl:variable name="paraPath" select="/books/book" ></xsl:variable>
</xsl:stylesheet>
在master.xslt中导入前面两个文件:
<xsl:import href="XSLT_Global.xslt"/>
<xsl:import href="XSLT_Comm.xslt"/>
xslt+xml+asp.net mvc简单的应用示例,如上有什么更好建议或想法,也请大家多多指点。