新开一个,不接着在《使用XSL设置布局,从asp.net页面中显示sql2005的数据》里回复,是因为这里使用了另一个以前没有用过的对象读取数据
ms sql 2000里,for xml语句,不可以设置root,所以读取出来的,不是完整的xml文件,用Northwind数据库做测试的
这个语句得到的是:
如果继续用原来的方法读取xml文件:
就会报错:
此文档已具有“DocumentElement”节点。
原因当然是因为一个xml文件只允许有一个根节点,现在有两个Products出现啊
我在这里卡了一下,因为以前没有用过XPathDocument,查了msdn后才知道这个对象,所以问题解决了
在这次测试里,我又加入了一个数据块,我是想旁边显示分类,中间显示类型,全部都要在xsl里定义布局,我测试到了
web.config文件
<connectionStrings>
<add name="db2000" connectionString="Data Source=服务品名;Initial Catalog=Northwind;User ID=数据库用户名;Password=数据库密码" providerName="System.Data.SqlClient" />
</connectionStrings>
定义目录布局的文件Category.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table align="center" width="150px" border="2">
<tbody>
<tr>
<th>Categories</th>
</tr>
<xsl:apply-templates select="//Categories"></xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="Categories">
<tr>
<td>
<xsl:value-of select="CategoryID"/>.
<xsl:value-of select="CategoryName"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
横向显示产品的文件:ProductH2000.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table align="center" width="600px" border="2">
<tbody>
<tr bgcolor="#CCFF99">
<th>ProductID</th>
<th>ProductName</th>
<th>UnitPrice</th>
</tr>
<xsl:apply-templates select="//Products"></xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="Products">
<tr>
<td>
<xsl:value-of select="ProductID"/>
</td>
<td>
<xsl:value-of select="ProductName"/>
</td>
<td>
<xsl:value-of select="UnitPrice"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
竖向显示产品的文件:ProductV2000.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table align="center" width="600px" border="2">
<tbody>
<xsl:apply-templates select="//Products"></xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="Products">
<tr>
<th>ProductID</th>
<td>
<xsl:value-of select="ProductID"/>
</td>
</tr>
<tr>
<th>ProductName</th>
<td>
<xsl:value-of select="ProductName"/>
</td>
</tr>
<tr>
<th>UnitPrice</th>
<td>
<xsl:value-of select="UnitPrice"/>
</td>
</tr>
<tr>
<td colspan="2"> </td>
</tr>
</xsl:template>
</xsl:stylesheet>
显示数据的aspx文件:T2000.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="T2000.aspx.cs" Inherits="database_T2000" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>连接sql2000数据库</title>
</head>
<body>
<form id="form1" runat="server">
<div style="float:left; width:160px; text-align:center;">
<asp:Literal ID="Literal2" runat="server"></asp:Literal>
</div>
<div style="float:left; width:610px; text-align:center;">
<div>
布局:
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"><asp:ListItem Value="H" Text="横版"></asp:ListItem><asp:ListItem Value="V" Text="竖版"></asp:ListItem></asp:DropDownList>
</div>
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
</div>
</form>
</body>
</html>
后置代码T2000.aspx.cs
using System;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.IO;
public partial class database_T2000 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (ViewState["layout"] == null) { ViewState["layout"] = "ProductH2000.xsl"; }
//读取目录和产品
string commandText, xslName;
commandText = "select CategoryID, CategoryName from Categories for xml auto, elements";
xslName = "Category.xsl";
ReadDataFromSql2000(commandText, xslName, Literal2);
//读取产品
commandText = "select ProductID, ProductName, UnitPrice from Products where ProductID < 10 for xml auto, elements";
xslName = ViewState["layout"].ToString();
ReadDataFromSql2000(commandText, xslName, Literal1);
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
switch (DropDownList1.SelectedValue)
{
case "H":
ViewState["layout"] = "ProductH2000.xsl";
break;
case "V":
ViewState["layout"] = "ProductV2000.xsl";
break;
}
//重新读取产品
string commandText, xslName;
commandText = "select ProductID, ProductName, UnitPrice from Products where ProductID < 10 for xml auto, elements";
xslName = ViewState["layout"].ToString();
ReadDataFromSql2000(commandText, xslName, Literal1);
}
private void ReadDataFromSql2000(string commandText, string xslName, Literal lt)
{
//连接数据库
string connectionString = ConfigurationManager.ConnectionStrings["db2000"].ConnectionString;
SqlConnection dbConnect = new SqlConnection(connectionString);
dbConnect.Open();
//读取数据
SqlCommand dbCommand = new SqlCommand(commandText, dbConnect);
XmlReader xr = dbCommand.ExecuteXmlReader();
//关闭数据库
dbConnect.Close();
//ShowDataFormXSL(xr);
ShowDataFromNodes(xr, xslName, lt);
}
private void ShowDataFromNodes(XmlReader xr, string xslName, Literal lt)
{
//使用XPathDocument数据模型读取数据
XPathDocument xPathDoc = new XPathDocument(xr);
//创建一个XslCompiledTransform对象
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Server.MapPath(xslName));
//使用XSL文件转换XML文件,结果输出到流
MemoryStream ms = new MemoryStream();
xslt.Transform(xPathDoc, null, ms);
//设置当前流中的位置是开头,后面可以从开头读起
ms.Seek(0, SeekOrigin.Begin);
//显示结果,从流的当前位置到末尾读取流
StreamReader sr = new StreamReader(ms);
lt.Text = sr.ReadToEnd();
}
}
页面运行后,得到的界面是这样子的:
横向
竖向
现在的问题是,整个界面的布局,我还是写在了aspx文件里了,如果,我要把对两个数据块的布局也写在xsl文件里呢?
我想,这样子的测试要停止下来了,我已经知道答案,知道这种东西是可以做的了,到看书的时候了,XSLT不是一个靠自己的脑袋和键盘测试就可以想通全部学懂的东西,要开始看《ASP.NET 2.0 XML 高级编程第3版》了