用XSL表现你的XML

我们已经知道,XML文件用来存放数据,而如何表现XML则要借助其他的手段。我们现在推荐您使用IE5.0。如果您在IE5.0中直接打开 一个XML文件,那么你看到的只是XML的源代码;要进一步以更灵活更丰富的形式来表示,就要借助于CSS或XSL。如何使用CSS,建议阅读CSS2规范(W3C建议) . 这里我们想介绍如何用XSL来表现您的XML.

首先我们给出一个XML文件(stock-sorter.xml)的简单例子:
<?xml:stylesheet type="text/xsl" href="simple.xsl"?>
<portfolio xmlns="x-schema:portfolio-schema.xml">
<description>Technology Stock Index</description>
<date>1999-08-13T15:56:00</date>

<stock>
<symbol>AOL</symbol>
<name>america online inc</name>
<price>92.250</price>
<change>-1.125</change>
<percent>-1.20</percent>
<volume>4.99</volume>
</stock>

<stock>
<symbol>CSCO</symbol>
<name>cisco sys inc</name>
<price>50.688</price>
<change>-1.688</change>
<percent>-3.22</percent>
<volume>18.23</volume>
</stock>

<stock>
<symbol>DELL</symbol>
<name>dell computer corp</name>
<price>53.000</price>
<change>-3.063</change>
<percent>-5.46</percent>
<volume>32.95</volume>
</stock>
......

</portfolio>

其中元素portfolio是在portfolio文件中定义的:

<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
<ElementType name="date" dt:type="dateTime"/>
<ElementType name="description"/>
<ElementType name="symbol"/>
<ElementType name="name"/>
<ElementType name="price" dt:type="fixed.14.4"/>
<ElementType name="change" dt:type="fixed.14.4"/>
<ElementType name="percent" dt:type="fixed.14.4"/>
<ElementType name="volume" dt:type="fixed.14.4"/>
<ElementType name="portfolio" content="eltOnly">
<group minOccurs="0" maxOccurs="1">
<element type="description" />
</group>
<group minOccurs="0" maxOccurs="1">
<element type="date" />
</group>
<group minOccurs="1" maxOccurs="1">
<element type="stock" />
</group>
</ElementType>
<ElementType name="stock" content="eltOnly">
<element type="symbol" />
<element type="name" />
<element type="price" />
<element type="change" />
<element type="percent" />
<element type="volume" />
</ElementType>
</Schema>

在stock-sorter.xml文件中第一行的处理指令(Process Instruction): <?xml:stylesheet type="text/xsl" href="simple.xsl"?> 表示由simple.xsl来规定XML的表现方式。当我们在IE中打开该XML时,浏览器根据其中所规定的XSL的位置去得到该XSL,并通过XSL 处理器将XML和XSL结合成为XSL定义的输出形式。这里我们将其输出形式定为HTML格式,是为了方便在浏览器中直接显示。好,让我们来看简单的XSL文件是怎样写的:

Simple.xsl:

<?xml version="1.0">
<HTML xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:9.5pt;background-color:#FEEEEE">
<xsl:for-each select="portfolio/stock">
<DIV STYLE="background-color:teal; color:white; padding:4px">
<SPAN STYLE="font-weight:bold; color:white">
<xsl:value-of select="name"/></SPAN>
- <xsl:value-of select="price"/>
</DIV>
<DIV STYLE="margin-left:10px; margin-bottom:1em; font-size:9pt">
<xsl:value-of select="description"/>
<SPAN STYLE="font-style:italic">
(change:<xsl:value-of select="change"/> )
</SPAN>
</DIV>
</xsl:for-each>
</BODY>
</HTML>

以上的代码很容易理解,关键是采用选择语句(for-each select)在XML树结构中进行选择,并把得到的结果树(Result Tree)包容于HTML中(value-of select).其实这只是简单的XSL语句.XSL的脚本语言叫做ECMAScript,它是在JavaScript的基础上发展的。如果我们要改变stock-sorter.xml的表现,只要在stlye sheet的href中指定另外的XSL文件。

XSL的规范定义了XML的匹配模板(Template),设置匹配字符,则处理时将从XML的根节点(Root Node)搜索匹配的节点.如:<xsl: template match="/">.通常构成HTML格式的模板,它可以只是XSL的一部分。您还可以写XSL的脚本,举个示例:

<xsl:script><![CDATA[
function Demo(node)
{
total = 0;
volumes = node.selectNodes("/portfolio/stock/volume");
for (v = volumes.nextNode(); v; v = volumes.nextNode())
total += v.nodeTypedValue;
return formatNumber(total, "#") + " million shares";
}
]]></xsl:script>

还可以加XSL的注释,如:

<xsl:comment><![CDATA[
function sort(field)
{
sortField.value = field;
listing.innerHTML = source.documentElement.transformNode(stylesheet);
}
]]></xsl:comment>

让我们给出另一个较为复杂的例子,并据此进一步学习XSL:

Complex.xsl:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<HTML>
<HEAD>
<STYLE>
BODY {margin:0}
.bg {font:8pt Verdana; background-color:purple; color:white}
H1 {font:bold 14pt Verdana; width:100%; margin-top:1em}
.row {font:8pt Verdana; border-bottom:1px solid #CC88CC}
.header {font:bold 9pt Verdana; cursor:hand; padding:2px; border:2px outset gray}
.up {background-color:#DDFFDD;}
.down {background-color:#FFDDDD;}
</STYLE>
</HEAD>

<SCRIPT>
<xsl:comment><![CDATA[
function sort(field)
{
sortField.value = field;
listing.innerHTML = source.documentElement.transformNode(stylesheet);
}
]]></xsl:comment>
</SCRIPT>

<SCRIPT for="window" event="onload">
<xsl:comment><![CDATA[
stylesheet = document.XSLDocument;
source = document.XMLDocument;
sortField = document.XSLDocument.selectSingleNode("//@order-by");
]]></xsl:comment>
</SCRIPT>

<BODY>
<TABLE width="100%" cellspacing="0">
<TR>
<TD class="bg"/>
<TD class="bg">
<H1> <xsl:value-of select="portfolio/description"/> for <xsl:apply-templates select="portfolio/date"/></H1>
<DIV>Average change: <B><xsl:eval>averageChange(this)</xsl:eval></B></DIV>
<DIV>Total volume: <B><xsl:eval>totalVolume(this)</xsl:eval></B></DIV>
</TD>
</TR>
<TR>
<TD class="bg" width="120" valign="top">
<P>Click on the column headers to sort by that field.</P>
<P>Demonstration of custom formatting of data typed values and local reapplication of the stylesheet.</P>
<P>Stocks losing more than 5% indicated in red. Stocks gaining value indicated in green.</P>
</TD>
<TD class="bg" valign="top">
<DIV id="listing"><xsl:apply-templates match="portfolio"/></DIV>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
</xsl:template>

<xsl:template match="portfolio">
<TABLE STYLE="background-color:white">

<THEAD>
<TD width="200"><DIV class="header" onClick="sort('name')">Company</DIV></TD>
<TD width="80"><DIV class="header" onClick="sort('symbol')">Symbol</DIV></TD>
<TD width="80"><DIV class="header" onClick="sort('price')">Price</DIV></TD>
<TD width="80"><DIV class="header" onClick="sort('change')">Change</DIV></TD>
<TD width="80"><DIV class="header" onClick="sort('percent')">%Change</DIV></TD>
<TD width="80"><DIV class="header" onClick="sort('volume')">Volume</DIV></TD>
</THEAD>

<xsl:for-each select="stock" order-by="symbol">
<TR>
<xsl:for-each select="change">
<xsl:if expr="this.nodeTypedValue &gt; 0">
<xsl:attribute name="class">up</xsl:attribute>
</xsl:if>
</xsl:for-each>

<xsl:for-each select="percent">
<xsl:if expr="this.nodeTypedValue &lt; -5">
<xsl:attribute name="class">down</xsl:attribute>
</xsl:if>
</xsl:for-each>
<TD><DIV class="row"><xsl:value-of select="name"/></DIV></TD>
<TD><DIV class="row"><xsl:value-of select="symbol"/></DIV></TD>
<TD><DIV class="row" STYLE="text-align:right"><xsl:apply-templates select="price"/></DIV></TD>
<TD><DIV class="row" STYLE="text-align:right"><xsl:apply-templates select="change"/></DIV></TD>
<TD><DIV class="row" STYLE="text-align:right"><xsl:apply-templates select="percent"/></DIV></TD>
<TD><DIV class="row" STYLE="text-align:right"><xsl:apply-templates select="volume"/></DIV></TD>
</TR>
</xsl:for-each>

</TABLE>

</xsl:template>

<xsl:template match="date">
<xsl:eval>formatDate(this.nodeTypedValue, "MMMM dd',' yyyy")</xsl:eval> at <xsl:eval>formatTime(this.nodeTypedValue, "hh:mm tt")</xsl:eval>
</xsl:template>

<xsl:template match="price | change">
<xsl:eval>formatNumber(this.nodeTypedValue, "$0.00")</xsl:eval>
</xsl:template>
<xsl:template match="percent">
<xsl:if expr="this.nodeTypedValue &gt; 0">+</xsl:if>
<xsl:eval>formatNumber(this.nodeTypedValue, "0.0")</xsl:eval>%
</xsl:template>

<xsl:template match="volume">
<xsl:eval>formatNumber(this.nodeTypedValue * 1000000, "#,###,###")</xsl:eval>
</xsl:template>


<xsl:script><![CDATA[
function totalVolume(node)
{
total = 0;
volumes = node.selectNodes("/portfolio/stock/volume");
for (v = volumes.nextNode(); v; v = volumes.nextNode())
total += v.nodeTypedValue;
return formatNumber(total, "#") + " million shares";
}

function averageChange(node)
{
total = 0;
percents = node.selectNodes("/portfolio/stock/percent");
count = percents.length;
for (p = percents.nextNode(); p; p = percents.nextNode())
total += p.nodeTypedValue;
return formatNumber(total/count, "#.0") + "%";
}

]]></xsl:script>

</xsl:stylesheet>

如果你要显示中文,你只要在XML和XSL文件的的开头分别加上:<?xml version="1.0" encoding="gb2312"?>即可.试试看!

你可能感兴趣的:(xml,css,IE,Cisco,XSL)