基于XML的电子公告系统
设计简单电子公告系统,无须关系数据库的支持,而是采用XML文档来保存用户所发布的电子公告和评论
系统逻辑结构图
- 添加评论:
- 添加公告:
电子公告和评论的XML文档
公告列表的XML文档: list.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="list.xsl"?>
<公告列表 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///E:/%e6%a1%8c%e9%9d%a2/XML%e6%9c%9f%e6%9c%ab/list.xsd" >
<公告>
<标题></标题>
<作者>/作者>
<发布时间></发布时间>
<内容></内容>
<文件名></文件名>
</公告>
<公告>
<标题></标题>
<作者></作者>
<发布时间></发布时间>
<内容></内容>
<文件名></文件名>
</公告>
<公告>
<标题></标题>
<作者></作者>
<发布时间></发布时间>
<内容></内容>
<文件名</文件名>
</公告>
<公告>
<标题></标题>
<作者></作者>
<发布时间></发布时间>
<内容></内容>
<文件名></文件名>
</公告>
</公告列表>
评论列表的XML文档:replys.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="replys.xsl"?>
<评论列表 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///E:/%e6%a1%8c%e9%9d%a2/XML%e6%9c%9f%e6%9c%ab/replys.xsd">
<公告>
<标题></标题>
<作者></作者>
<发布时间></发布时间>
<内容></内容>
</公告>
<评论>
<标题></标题>
<作者></作者>
<评论时间></评论时间>
<内容></内容>
</评论>
<评论>
<标题></标题>
<作者></作者>
<评论时间></评论时间>
<内容></内容>
</评论>
</评论列表>
相应Schema定义
公告列表: list.xsd
<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XMLSpy v2013 (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="标题" type="xs:token"/>
<xs:element name="文件名" type="xs:token"/>
<xs:element name="发布时间" type="xs:token"/>
<xs:element name="作者" type="xs:token"/>
<xs:element name="br">
<xs:complexType/>
</xs:element>
<xs:element name="公告列表">
<xs:complexType>
<xs:sequence>
<xs:element ref="公告" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="公告">
<xs:complexType>
<xs:sequence>
<xs:element ref="标题"/>
<xs:element ref="作者"/>
<xs:element ref="发布时间"/>
<xs:element ref="内容"/>
<xs:element ref="文件名"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="内容">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element ref="br" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
评论列表 replys.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XMLSpy v2013 (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="评论时间">
<xs:complexType/>
</xs:element>
<xs:element name="评论列表">
<xs:complexType>
<xs:sequence>
<xs:element ref="公告"/>
<xs:element ref="评论" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- 定义评论元素类型-->
<xs:element name="评论">
<xs:complexType>
<xs:sequence>
<xs:element ref="标题"/>
<xs:element ref="作者"/>
<xs:element ref="评论时间"/>
<xs:element ref="内容"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- 定义内容元素类型 -->
<xs:complexType name="内容">
<!-- 可以包含多个br元素 -->
<xs:sequence>
<xs:element ref="br" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="标题">
<xs:complexType/>
</xs:element>
<xs:element name="发布时间">
<xs:complexType/>
</xs:element>
<xs:element name="内容">
<xs:complexType/>
</xs:element>
<xs:element name="作者">
<xs:complexType/>
</xs:element>
<xs:element name="br">
<xs:complexType/>
</xs:element>
<!-- 定义公告元素可以包括多个元素-->
<xs:element name="公告">
<xs:complexType>
<xs:sequence>
<xs:element ref="标题"/>
<xs:element ref="作者"/>
<xs:element ref="发布时间"/>
<xs:element ref="内容"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
相应的样式表 --设置显示的样式
公告列表 list.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="/">
<!-- TODO: Auto-generated template -->
<html>
<head>
<title>公告列表</title>
</head>
<body>
<table width="780" align= "center" background=" img/2.jpg">
<tr>
<td height="5" colspan="3"><hr /></td>
</tr>
<!-- 对公告列表元素起作用 -->
<xsl:apply-templates select="公告列表"/>
<tr>
<td height="5" colspan="3">
<form action="AddNews" method="post">
标题: <input type="text" name="title"/><br/>
作者: <input type="text" name="user"/><br/>
内容: <br/><textarea name="content" cols="50" rows="10"/><br/>
<input type="submit" value=" 发布"/>
</form>
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
<!-- 为公告列表定义转换模板 -->
<xsl:template match="公告">
<tr>
<td class="mytitle" colspan="3"><xsl:value-of select="标题"/></td>
</tr>
<tr>
<td colspan="3"><span>日期: <xsl:value-of select= "发布时间"/></span>
<span>作者: <xsl:value-of select="作者"/></span>
<span><a href="replysList?file=replys.xml">查看、发表评论</a></span>
</td>
</tr>
<tr>
<td colspan="3"><div class= "content">
<!--将内容元素下的文本节点、br元素复制到结果文档中-->
<xsl:copy-of select="内容/text() | 内容/br"/>
</div>
</td>
</tr>
<tr>
<td colspan=" 3 ">
<span class= "comment-sub"></span><hr/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
评论列表 replys.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="/">
<!-- TODO: Auto-generated template -->
<html>
<head>
<title>评论列表</title>
<link href=" images/css.css." rel="stylesheet" type="text/css"/>
</head>
<body>
<table width="780" align= "center" background=" img/1.jpg">
<tr>
<td height="5" colspan="3"><hr /></td>
</tr>
<!-- 处理评论列表元素 -->
<xsl:apply-templates select="评论列表"/>
<tr>
<td height="5" colspan="3">
<form action="AddReply" method="post">
标题: <input type="text" name="title"/><br/>
作者: <input type="text" name="user"/><br/>
内容: <br/><textarea name="content" cols="50" rows="10"/><br/>
<input type="submit" value=" 我想评论"/>
</form>
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="评论列表">
<!--处理公告元素-->
<xsl:apply-templates select="公告"/>
<!--处理评论元素 -->
<xsl:apply-templates select="评论"/>
</xsl:template>
<xsl:template match="公告">
<tr>
<td class="mytitle" colspan="3"><xsl:value-of select="标题"/></td>
</tr>
<tr>
<td colspan="3">
<span><a href="list.xml">返回首页</a></span>
</td>
</tr>
<tr>
<td colspan="3"><div class= "content">
<!--将内容元素下的文本节点、br元素复制到结果文档中-->
<xsl:copy-of select="内容/text() | 内容/br"/>
</div>
</td>
</tr>
<tr>
<td colspan=" 3 ">
<span class= "comment-sub">以下是用户对此公告的评论</span><hr/>
</td>
</tr>
</xsl:template>
<xsl:template match="评论">
<tr>
<td colspana="3" >
<div class= "comment">
<div class="ctitle">
<xsl:value-of select="标题" />
<span style=" font-size:9pt; padding-left :20px" >
<xsl:value-of select="作者"/>
于<xsl:value-of select= "评论时间"/>评论</span>
</div>
<div>
<!--将内容元素下的文本节点、br元素复制到结果文档中-->
<xsl:copy-of select="内容/text() |内容/br"/>
</div>
</div>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
实现控制器
- 添加公告 AddNews.java
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.io.SAXReader;
/**
* Servlet implementation class AddNews
*/
@WebServlet("/AddNews")
public class AddNews extends HttpServlet {
private static final long serialVersionUID = 1L;
public AddNews() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置解码方式
request.setCharacterEncoding("UTF-8");
//获取新发的公告的标题,作者,内容
String title = request.getParameter("title");
String user= request.getParameter("user");
String content = request.getParameter("content");
//验证公告的内容,标题不能为空
if(title == null || title.trim().equals("") || content == null || content.trim().equals("")) {
//重定向的 list.xml文件
response.sendRedirect("list.xml");
}else {
//获取list.xml的绝对路径
String path = getServletContext().getRealPath("/list.xml");
try {
SAXReader reader = new SAXReader();
reader.setStripWhitespaceText(true);
reader.setMergeAdjacentText(true);
Dom4jWrite dw= new Dom4jWrite();
dw.addElement(path,title,user,content);
dw.addNews(title, user, content, path);
}
catch (Exception e){
e.printStackTrace();
System.out.println("Dom4j错误");
}
//重定向的list.xml文档
response.sendRedirect("list.xml");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
- 添加评论 AddReply.java
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class AddReply
*/
@WebServlet("/AddReply")
public class AddReply extends HttpServlet {
private static final long serialVersionUID = 1L;
String[] f;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding ("UTF-8") ;
HttpSession session = request.getSession() ;
String title = request.getParameter("title") ;
String user = request.getParameter ("user");
String content = request.getParameter ("Content");
//获取Referer请求头的值,通过该请求头来获取正在浏览的评论列表XML文档
String path = request.getHeader ("Referer") ;
String file ="";
//获取保存评论信息的XML文件的文件名
if (path != null && path.indexOf("=") >= 0) {
f = path.split("=") ;
file = f[1];
session. setAttribute("file", file);
}else {
file = (String) session.getAttribute("file") ;
}
if (file.trim().equals("")) {
//如果file参数为空字符串,重定向到list.xml
response.sendRedirect("list.xm1") ;
}else {
//截断file参数前后的空格
file = file.trim();
//验证回复标题、内容不能为空
if (title== null || title.trim().equals("") || content == null || content.trim().equals("")) {
request .getRequestDispatcher ("/replysList?file=" + file). forward(request, response);
}else {
try {
//获取回复XML文档的绝对路径
String filePath = getServletContext ().getRealPath(" /WebContent/" + file) ;
//创建Dom4 jWrite解析器的实例
Dom4jWrite dw = new Dom4jWrite();
dw.addReply(filePath, title, user, content);
}
catch(Exception e){
e.printStackTrace();
}
//再次将刚刚查看的评论列表XML文档作为响应输出
request.getRequestDispatcher ("/replysList?file=" + file).forward(request, response) ;
}
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
- 查看评论列表 ReplysList.java
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ReplysList
*/
@WebServlet("/replysList")
public class ReplysList extends HttpServlet {
private static final long serialVersionUID = 1L;
public ReplysList() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置解码方式
request.setCharacterEncoding ("UTF-8") ;
ServletContext application = getServletContext () ;
//获取文件名
String file = request.getParameter("file") ;
System.out.println(file);
//如果file参数不存在
if (file == null || file.trim().equals("") ) {
//重定向到list.xml
response.sendRedirect ("list.xml") ;
}else {
//以file参数指定的XML文档作为响应
request.getRequestDispatcher (file.trim() ).forward(request, response) ;
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
- 数据的修改 — Dom4jWrite
Dom4jWrite的主要作用是访问XML文档,当系统需要添加公告和评论时,Dom4jWrite负责去操作XML
package com.servlet;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
//@WebServlet("/addReply")
public class Dom4jWrite extends HttpServlet{
public void addElement (String path, String title, String user, String content) throws Exception{
SAXReader reader = new SAXReader();
Document doc = reader.read(new File(path));
Element root = doc.getRootElement();
SimpleDateFormat dt= new SimpleDateFormat("yyyy--mm--dd");
//添加新的<公告>节点
Element note = root.addElement("公告");
Element noteTitle = note.addElement("标题");
noteTitle.setText(title);
Element noteUser = note.addElement("作者");
noteUser.setText(user);
Element noteDate = note.addElement("发布时间");
java.util.Date date= new java.util.Date();
String dateTime = dt.format(date);
noteDate.setText(dateTime+"");
Element noteContent = note.addElement("内容");
// //将content 字符串以换行符号分割为多个字符串
// String[] contents = content.split("\r\n");
// //将新闻内容中的换行替换成HTML 中的换行符<br>
// for (int i = 0; i<content.length(); i++) {
// noteContent.addCDATA(contents[i]);
// //每添加一个字符串之后,添加一个空的br 元素
// if(i != contents.length-1) {
// noteContent.addElement("br");
// }
//
// }
Element noteFile = note.addElement("文件名");
noteFile.setText(date+"");
OutputFormat format= new OutputFormat(" ", true, "GBK");
FileWriter fw = new FileWriter(path);
XMLWriter writer = new XMLWriter(fw, format);
//将修改过的XML文档重新写入磁盘文件
writer.write(doc);
fw.close();
}
public void addNews(String title, String user, String content, String path) throws IOException {
DocumentFactory factory = new DocumentFactory();
Document doc = factory.createDocument();
//添加处理指令
doc.addProcessingInstruction("xml-stylesheet type=\"text/xsl\" href=\"replys.xslt\"", "");
//为XML文档创建根元素
Element root = doc. addElement ("评论列表");
root.add(new Namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
root. addAttribute("xsi :noNamespaceSchemaLocation", " replys.xsd");
//新增一个<公告.../>子节点
Element note = root.addElement("公告");
//为<公告.../>节点依次添加4个子节点
Element noteTitle = note.addElement ("标题");
noteTitle.setText(title) ;
Element noteUser = note. addElement ("作者");
noteUser.setText (user) ;
Element noteDate = note.addElement ("发布时间");
SimpleDateFormat dt= new SimpleDateFormat("yyyy--mm--dd");
java.util.Date date= new java.util.Date();
String dateTime = dt.format(date);
noteDate.setText (dateTime +"") ;
Element noteContent = note.addElement ("内容");
// String[] contents = content.split("\r\n");
// //将公告内容中的换行替换成HTML换行符<br />2
// for (int i =0;i< contents.length ; i ++) {
// noteContent.addCDATA (contents[i]) ;
// if (i != contents.length-1) {
// noteContent. addElement ("br") ;
// }
// }
//将新建的XML文档写到磁盘文件中
OutputFormat format = new OutputFormat(" ", true, "GBK") ;
int index = path.lastIndexOf("\\") ;
String filePath = path.substring(0, index) ;
FileWriter fw = new FileWriter (filePath +"/list.xml"+ dateTime+".xm1") ;
XMLWriter writer = new XMLWriter (fw, format);
writer.write(doc) ;
fw.close() ;
}
//把评论内容写入相应的XML文件中,即向其中添加一个<评论.../>节点
public void addReply(String filePath, String title, String user,String content) throws Exception{
//以指定XML文档创建Document
SAXReader reader = new SAXReader();
Document doc = reader.read (new File (filePath)) ;
//获取XML文档的根节点
Element root = doc. getRootElement() ;
//添加<评论.../>节点
Element note = root.addElement ("评论") ;
//为<评论.../>节点依次添加4个子节点
Element noteTitle = note.addElement ("标题") ;
noteTitle.setText (title) ;
Element noteUser = note.addElement ("作者") ;
noteUser .setText (user) ;
Element noteDate = note.addElement ("评论时间") ;
SimpleDateFormat dt= new SimpleDateFormat("yyyy--mm--dd");
java.util.Date date= new java.util.Date();
String dateTime = dt.format(date);
noteDate.setText (dateTime +"");
Element noteContent = note.addElement ("内容") ;
// String[] contents = content.split("\r\n");
// //将新闻内容中的换行替换成HTML换行符<br />
// for (int i =0;i < contents.length-1; i ++) {
// noteContent.addCDATA (contents[i]) ;
// if(i != contents.length-1) {
// noteContent.addElement ("br") ;
// }
// }
OutputFormat format = new OutputFormat (" ", true, "GBK") ;
FileWriter fw = new FileWriter (filePath);
XMLWriter writer= new XMLWriter(fw, format) ;
//将修改过的XML文档重新写入磁盘文件中
writer.write(doc) ;
fw.close() ;
}
}