代码改变世界

xml文件操作之XSLT

2012-03-19 16:02  AceYue  阅读(4683)  评论(4编辑  收藏  举报

      最近接手的一个项目中数据的获取通过数据库与xml文件双向处理,不知出入什么原因,该项目的先前设计者将数据从数据库取出后又写入到xml文件中,然后从xml文件中读取数据。由于数据量大的原因,项目中几个文件夹加载时浏览器一度崩溃,无赖只得对数据进行优化。本来sql server支持分页与排序操作,起初我打算重写这个存储过程,但是之前的存储过程之后发现代码比较混乱,足有200多行的代码,兵来将挡,一个上午的时间将先前的存储过程重新整理修改支持了分页自定义排序及搜索功能。本以为可以轻松,却发现任有几个文件夹不支持分页功能,原来这些文件中的文件只从数据库中取出部分数据,然后与xml文件交互后取出数据,多么蛋疼的事情,无赖只得找解决方案。网上搜索资料引出今天的主题——XSLT(EXtensible Stylesheet Language Transformations)。

      XSLT 在 1999 年 11 月 16 日被确立为 W3C 标准,现在几乎所有的浏览器都支持XML和XSLT。XSLT 用于将一种 XML 文档转换为另外一种 XML 文档,或者可被浏览器识别的其他类型的文档,比如 HTML 和 XHTML。通常,XSLT 是通过把每个 XML 元素转换为 (X)HTML 元素来完成这项工作的。通过 XSLT,您可以向或者从输出文件添加或移除元素和属性。您也可重新排列元素,执行测试并决定隐藏或显示哪个元素,等等。

      下面进入正题如何使用XSLT:

       我们使用vs工具新建一个xslt文件,新建的文件中有如下默认代码:

View Code
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl
="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

首先xslt文件也是一个xml文件,其语法同样以<?xml version="1.0" encoding="utf-8"?>头开始。

<xsl:stylesheet> 为xsl文件的根节点,也可使用<xsl:transform>。

xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 指向了官方的 W3C XSLT 命名空间。
version="1.0" 指定xsl文件的版本号。

<xsl:output method="xml" indent="yes"/> 定义输出文本的格式。

<xsl:template> 元素用于构建模板。

match 属性用于关联 XML 元素和模板。match 属性也可用来为整个文档定义模板。match 属性的值是 XPath 表达式(举例,match="/" 定义整个文档)。

......

XSLT的更多属性:

元素描述IEN
apply-imports 应用来自导入样式表中的模版规则。 6.0  
apply-templates 向当前元素或当前元素的子元素应用模板。 5.0 6.0
attribute 向元素添加属性。 5.0 6.0
attribute-set 创建命名的属性集。 6.0 6.0
call-template 调用一个指定的模板。 6.0 6.0
choose 与<when>以及<otherwise>协同使用,来表达多重条件测试。 5.0 6.0
comment 在结果树中创建注释节点。 5.0 6.0
copy 创建当前节点的一个备份(无子节点及属性)。 5.0 6.0
copy-of 创建当前节点的一个备份(带有子节点及属性)。 6.0 6.0
decimal-format 定义当通过 format-number() 函数把数字转换为字符串时,所要使用的字符和符号。 6.0  
element 在输出文档中创建一个元素节点。 5.0 6.0
fallback 假如处理器不支持某个XSLT元素,规定一段备用代码来运行。 6.0  
for-each 遍历指定的节点集中的每个节点。 5.0 6.0
if 包含一个模板,仅当某个指定的条件成立时应用此模板。 5.0 6.0
import 用于把一个样式表中的内容倒入另一个样式表中。 6.0 6.0
include 把一个样式表中的内容包含到另一个样式表中。 6.0 6.0
key 声明一个命名的键。 6.0 6.0
message 向输出写一条消息(用于错误报告)。 6.0 6.0
namespace-alias 把样式表中的命名空间替换为输出中不同的命名空间。 6.0  
number 测定当前节点的整数位置,并对数字进行格式化。 6.0 6.0
otherwise 规定 <choose> 元素的默认动作。 5.0 6.0
output 定义输出文档的格式。 6.0 6.0
param 声明一个局部或全局参数。 6.0 6.0
preserve-space 用于定义保留空白的元素。 6.0 6.0
processing-instruction 生成处理指令节点。 5.0 6.0
sort 对结果进行排序。 6.0 6.0
strip-space 定义应当删除空白字符的元素。 6.0 6.0
stylesheet 定义样式表的根元素。 5.0 6.0
template 当指定的节点被匹配时所应用的规则。 5.0 6.0
text 通过样式表生成文本节点。 5.0 6.0
transform 定义样式表的根元素。 6.0 6.0
value-of 提取选定节点的值。 5.0 6.0
variable 声明局部或者全局的变量。 6.0 6.0
when 规定 <choose> 元素的动作。 5.0 6.0
with-param 规定需被传入某个模板的参数的值。 6.0 6.0

下面用具体的实例来说明xslt的用法:

book.xml文件:

View Code
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="book.xslt"?>
<books>
<book>
<title>C#</title>
<description>C#开发宝典</description>
<price>85</price>
</book>
<book>
<title>java</title>
<description>java开发宝典</description>
<price>78</price>
</book>
<book>
<title>php</title>
<description>php开发宝典</description>
<price>33</price>
</book>
<book>
<title>C</title>
<description>C语言开发宝典</description>
<price>95</price>
</book>
</books>

我们使用book.xslt将book.xml文件转换成浏览器可读文件,book.xslt:

View Code
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl
="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="books">
<html>
<head>MY book</head>
<body>
<table border="1">
<tr bgcolor="#9acd32">
<th>title</th>
<th>description</th>
<th>price</th>
</tr>

<xsl:for-each select="book">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="description"/>
</td>
<td>
<xsl:value-of select="price"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

使用<?xml-stylesheet type="text/xsl" href="book.xslt"?>在book.xml文件中关联book.xslt文件在浏览器中浏览结果:

解析:

<xsl:for-each> 元素可用于选取指定的节点集中的每个 XML 元素。

<xsl:value-of> 元素用于提取某个选定节点的值,并把值添加到转换的输出流中。

select 属性的值是一个 XPath 表达式。此表达式的工作方式类似于定位某个文件系统,在其中正斜杠可选择子目录。

 

 xmlt高级应用:

    以上介绍了如何将一个xml文件转换成为(x)html,下面看看xslt的高级用法。

    <xsl:if> 元素用于针对 XML 文件的内容放置一个条件测试。

    <xsl:choose> 元素被用来与 <xsl:when> 和 <xsl:otherwise> 配合使用,来表达多重的条件检验。

   如:

View Code
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl
="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="books">
<html>
<head>MY book</head>
<body>
<table border="1">
<tr bgcolor="#9acd32">
<th>title</th>
<th>description</th>
<th>price</th>
</tr>
<xsl:for-each select="book">
<xsl:if test="price &gt; 60">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="description"/>
</td>
<xsl:choose>
<xsl:when test="price &gt; 90">
<td bgcolor="#FFFFF">
<xsl:value-of select="price"/>
</td>
</xsl:when>
<xsl:otherwise>
<td bgcolor="#FOOFF">
<xsl:value-of select="price"/>
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

浏览器中查看:

 

   <xsl:sort> 元素用于对输出进行排序。

View Code
<xsl:for-each select="book">
<xsl:sort select="price" order="ascending"/>
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="description"/>
</td>
<td>
<xsl:value-of select="price"/>
</td>
</tr>
</xsl:for-each>

浏览结果:

 

<xsl:apply-templates> 元素可把模板规则应用到当前节点或者当前元素的子节点。

下面用一个实例来讲xsl:apply_templates的用法及xslt分页:

xslt文件:

View Code
<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" media-type="text/plain"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="//Lines">
<xsl:element name="Lines">
<xsl:apply-templates select="//Lines/Line" >
<xsl:sort select="@FieldName" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>

<xsl:template match="//Lines/Line">
<xsl:if test="ceiling(position() div 50) = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

xml文件过大不便全部贴出,这里只贴出格式:

View Code
<Lines>
<Line FieldID="559" FieldCode="" FieldName="Zip/Postal Code" FieldDesc="Zip / Postal Code" FieldTypeID="6" FieldTypeName="Text" CreatorID="-" CreatorName="-" StatusID="1" StatusDesc="Enabled" CategoryID="11" CategoryName="-" EntityID="4" EntityName="-" CreateDate="-" SystemField="0" FilledBy="Applicant" SystemFieldDesc="N" Required="0" RequiredDesc="N" TypeID="1" IsEdit="1" IsHRIS="0" Chk="" Parse="N" />
<Line FieldID="540" FieldCode="" FieldName="Specialized SkillsAccounting" FieldDesc="Specialized Skills Please specify if you are specialized in any accounting skills" FieldTypeID="6" FieldTypeName="Text" CreatorID="-" CreatorName="-" StatusID="1" StatusDesc="Enabled" CategoryID="11" CategoryName="-" EntityID="4" EntityName="-" CreateDate="-" SystemField="0" FilledBy="Applicant" SystemFieldDesc="N" Required="0" RequiredDesc="N" TypeID="1" IsEdit="1" IsHRIS="0" Chk="" Parse="N" />
。。。。。。
</Lines>

 

XSLT在客户端应用

      在浏览器中把 XML 转换为 XHTML,我们使用javascript来转换:

View Code
<div>
<script type="text/javascript">
var xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async
= false;
xml.load(
"book.xml");

var xsl = new ActiveXObject("Microsoft.XMLDOM");
xsl.async
= false;
xsl.load(
"book.xslt");

document.write(xml.transformNode(xsl));
</script>
</div>

      第一段代码创建了微软的 XML 解析器的一个实例,然后把 XML 文件载入了内存。第二段代码创建了解析器的另一个实例,然后把这个 XSL 文件载入了内存。最后一行代码使用 XSL 文档转换了 XML 文档,并在浏览器中把结果作为 XHTML 显示出来。任务完成!

本人也是xslt初学者,文章中有错误之处请谅解,欢迎提出修改意见,谢谢!

 

注:本文为作者原创,欢迎转载,转载请注明出处:www.cnblogs.com/aces