1 下列XML文档中,符合XML语法规范的是

A.

<customer>
	  <address>123 MainStreet></Address>
</customer>

B.

<customer>
  <name>Joe’s XML Works</name>
  <address>New York
</costomer>

C.

<customer type=extemal>
  <name>Partners Unlimited</name>
</customer>

D.

<customer name="JohnDoe">
  <address>123 Main  Street</address> 
  <zip code="01837"/>
</customer>

参考答案

本题正确答案为D。

AB选项,不符合XML语法规范。在XML中,元素要成对出现,而且大小写敏感。A选项元素address的结尾为</Address>,“A”字母要小写。B选项元素<address>没有结尾标记。

C选项,不符合XML语法规范。在XML中,属性必须被引号包围,不过单引号和双引号均可使用。

2 简述SAX和DOM解析方式的不同

参考答案

DOM:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成各个Node对象(节点)。

优点:把xml文件在内存中构造树形结构,可以遍历和修改节点

缺点:如果文件比较大,内存有压力,解析的时间会比较长

SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析。

优点: 解析可以立即开始,速度快,没有内存压力

缺点: 不能对节点做修改

3 客户端以XML格式向服务器端发送数据V1

客户端以XML格式向服务器端发送数据,详细要求如下:

1)客户端读取EmpList.xml数据,将其发送到服务器端。

2)服务器接收到XML格式的数据后,进行解析,将解析到的数据输出到控制台。

参考答案

实现此案例需要按照如下步骤进行。

步骤一:导入dom4j对应的jar包

在当前工程下导入dom4j对应的jar包。

步骤二:创建服务器端Server类

首先,新建类Server;然后在该类的main方法中创建ServerSocket对象,监听客户端的连接以及网络输入流对象,代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤三:创建SAXReader类的对象,获取Document对象

首先,创建SAXReader类的对象来实现读取XML文档;然后,使用SAXReader类的read方法获取Document对象,代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
#cold_bold			SAXReader reader = new SAXReader();
#cold_bold			System.out.println("开始解析客户端发送的xml");
#cold_bold//读取指定文件
#cold_bold			Document doc = reader.read(in);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
} 

步骤四:获取根元素

使用Document对象的getRootElement方法获取EmpList.xml文档的根元素,代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取指定文件
			Document doc = reader.read(in);
			//获取跟节点list
			Element root = doc.getRootElement();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤五:获取<list>元素下的所有子元素

使用Element对象的elements方法获取<list>元素下的所有子元素,即所有的<emp>节点,代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取指定文件
			Document doc = reader.read(in);
			//获取跟节点list
			Element root = doc.getRootElement();
			//获取list下的所有子节点emp
#cold_bold			List<Element> elements = root.elements();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤六:封装Emp对象,存储到List集合中

1)创建存储的数据类型为Emp类型的List集合emps;

2)循环上一步中的elements集合,每循环一次获取一个emp元素。在循环中使用Element对象的attribute方法获取id属性对应的Attribute对象,再使用Attribute对象的getValue方法就可以获取到属性id对应的文本信息,即Emp对象的属性id的信息;

3)在循环中,使用Element对象的elementText方法获取节点<name>、<age>、<gender>以及<salary>对应的文本信息,即Emp对象的属性name、age、gender以及salary。

4)在循环中,将上述获取到的信息封装为Emp对象,存储到集合emps中。

代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取指定文件
			Document doc = reader.read(in);
			//获取跟节点list
			Element root = doc.getRootElement();
			//获取list下的所有子节点emp
			List<Element> elements = root.elements();
			//保存所有员工对象的集合
#cold_bold			List<Emp> emps = new ArrayList<Emp>();
#cold_bold			for(Element element : elements){			
#cold_bold				int id = Integer.parseInt(element.attribute("id").getValue());
#cold_bold				String name = element.elementText("name");
#cold_bold				int age = Integer.parseInt(element.elementText("age"));
#cold_bold				String gender = element.elementText("gender");
#cold_bold				double salary = Double.parseDouble(element.elementText("salary"));
#cold_bold				Emp emp = new Emp(id,name,age,gender,salary);
#cold_bold				emps.add(emp);
#cold_bold			}
#cold_bold			System.out.println("解析完毕");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤七:输出集合

将emps集合的信息输出到控制台并关闭Socket对象,代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取指定文件
			Document doc = reader.read(in);
			//获取跟节点list
			Element root = doc.getRootElement();
			//获取list下的所有子节点emp
			List<Element> elements = root.elements();
			//保存所有员工对象的集合
			List<Emp> emps = new ArrayList<Emp>();
			for(Element element : elements){			
				int id = Integer.parseInt(element.attribute("id").getValue());
				String name = element.elementText("name");
				int age = Integer.parseInt(element.elementText("age"));
				String gender = element.elementText("gender");
				double salary = Double.parseDouble(element.elementText("salary"));
				Emp emp = new Emp(id,name,age,gender,salary);
				emps.add(emp);
			}
			System.out.println("解析完毕");
#cold_bold			System.out.println(emps);
#cold_bold			server.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤八: 创建客户端Client类

新建类Client,在该类的main方法中,首先,创建Socket去连接服务器端;然后获取网络输出流,代码如下所示:

import java.io.File;
import java.io.OutputStream;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Client {
	public static void main(String[] args) {
		try {
			//连接服务端
			Socket socket = new Socket("127.0.0.1",8088);
			//获取输出流
			OutputStream out = socket.getOutputStream();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤九: 读取XML文档

创建SAXReader对象,来读取XML文档,并获取Document对象,代码如下所示:

import java.io.File;
import java.io.OutputStream;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Client {
	public static void main(String[] args) {
		try {
			//连接服务端
			Socket socket = new Socket("127.0.0.1",8088);
			//获取输出流
			OutputStream out = socket.getOutputStream();
#cold_bold			//创建SAXReader
#cold_bold			SAXReader reader = new SAXReader();
#cold_bold			//读取指定文件
#cold_bold			Document doc = reader.read(new File("EmpList.xml"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤十:发送XML文件到服务器端

首先,创建XML输出流XMLWriter类的对象;然后,设置该XML输出流的字节输出流为网络输出流out;最后,将Document对象写出到服务器端并关闭Socket对象,代码如下所示:

import java.io.File;
import java.io.OutputStream;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Client {
	public static void main(String[] args) {
		try {
			//连接服务端
			Socket socket = new Socket("127.0.0.1",8088);
			//获取输出流
			OutputStream out = socket.getOutputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			//读取指定文件
			Document doc = reader.read(new File("EmpList.xml"));
			//创建XML输出流
#cold_bold			XMLWriter writer = new XMLWriter();
#cold_bold			writer.setOutputStream(out);
#cold_bold			writer.write(doc);
#cold_bold			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

步骤十一: 测试

运行代码,首先启动服务器端,然后启动客户端,服务器端控制台输出结果如下所示:

等待客户端连接
客户端已经连接
开始解析客户端发送的xml
解析完毕
[Emp [id=1,name=张三, age=34, gender=男, salary=3000.0], Emp [id=2,name=李四, age=21, gender=女, salary=4000.0], Emp [id=3,name=王五, age=46, gender=女, salary=6500.0], Emp [id=4,name=赵六, age=28, gender=男, salary=4400.0], Emp [id=5,name=钱七, age=53, gender=男, salary=12000.0]]

本案例中,Emp类的完整代码如下所示:

/**
 * 描述xml文件中每一个员工信息
 */
public class Emp {
	private int id;
	private String name;
	private int age;
	private String gender;
	private double salary;

	public Emp(int id,String name, int age, String gender, double salary) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.salary = salary;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Emp [id=" + id + ",name=" + name + ", age=" + age + ", gender=" + gender
				+ ", salary=" + salary + "]";
	}
}

Server类的完整代码如下所示:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取指定文件
			Document doc = reader.read(in);
			//获取跟节点list
			Element root = doc.getRootElement();
			//获取list下的所有子节点emp
			List<Element> elements = root.elements();
			//保存所有员工对象的集合
			List<Emp> emps = new ArrayList<Emp>();
			for(Element element : elements){			
				int id = Integer.parseInt(element.attribute("id").getValue());
				String name = element.elementText("name");
				int age = Integer.parseInt(element.elementText("age"));
				String gender = element.elementText("gender");
				double salary = Double.parseDouble(element.elementText("salary"));
				Emp emp = new Emp(id,name,age,gender,salary);
				emps.add(emp);
			}
			System.out.println("解析完毕");
			System.out.println(emps);
			server.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Client类的完整代码如下所示:

import java.io.File;
import java.io.OutputStream;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Client {
	public static void main(String[] args) {
		try {
			//连接服务端
			Socket socket = new Socket("127.0.0.1",8088);
			//获取输出流
			OutputStream out = socket.getOutputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			//读取指定文件
			Document doc = reader.read(new File("EmpList.xml"));
			//创建XML输出流
			XMLWriter writer = new XMLWriter();
			writer.setOutputStream(out);
			writer.write(doc);		
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

4 客户端以XML格式向服务器端发送数据V2(提高题,选做)

客户端以XML格式向服务器端发送数据,详细要求如下:

1)客户端读取EmpList.xml中的数据,将其发送到服务器端。

2)服务器接收到XML格式的数据后,将其输出到Emp_Server.xml文件中。

参考答案

在上一案例中,是将客户端发送来的EmpList.xml解析输出到控制台,本案例要求将客户端发送来的XML格式的数据输出到Emp_Server.xml文件中,即,我们只要将服务器端Server类解析输出到控制台的代码,改为将XML格式的数据输出到Emp_Server.xml文件即可。

实现此案例需要按照如下步骤进行。

步骤一:修改Server类

修改Server类,将解析输出到控制台的代码,改为将XML格式的数据输出到Emp_Server.xml文件,代码如下所示:

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取用户发送过来的xml
			Document doc = reader.read(in);
			//写出XML
#cold_bold			XMLWriter writer = new XMLWriter();
#cold_bold			FileOutputStream fos = new FileOutputStream("Emp_Server.xml");
#cold_bold			writer.setOutputStream(fos);
#cold_bold			writer.write(doc);
#cold_bold			writer.close();
#cold_bold			server.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

运行代码,首先启动服务器端,然后启动客户端,在你当前工程目录下会生成emp_server.xml文件。文件内容与EmpList.xml文件内容相同。

本案例中,Emp类的完整代码如下所示:

/**
 * 描述xml文件中每一个员工信息
 */
public class Emp {
	private int id;
	private String name;
	private int age;
	private String gender;
	private double salary;

	public Emp(int id,String name, int age, String gender, double salary) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.salary = salary;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Emp [id=" + id + ",name=" + name + ", age=" + age + ", gender=" + gender + ", salary=" + salary + "]";
	}
}

Server类的完整代码如下所示:

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Server {
	public static void main(String[] args) {
		try {
			//创建服务端Socket
			ServerSocket server = new ServerSocket(8088);
			System.out.println("等待客户端连接");
			//监听客户端连接
			Socket socket = server.accept();
			System.out.println("客户端已经连接");
			//获取输入流
			InputStream in = socket.getInputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			System.out.println("开始解析客户端发送的xml");
			//读取用户发送过来的xml
			Document doc = reader.read(in);
			//写出XML
			XMLWriter writer = new XMLWriter();
			FileOutputStream fos = new FileOutputStream("Emp_Server.xml");
			writer.setOutputStream(fos);
			writer.write(doc);
			writer.close();
			server.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
}

Client类的完整代码如下所示:

import java.io.File;
import java.io.OutputStream;
import java.net.Socket;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Client {
	public static void main(String[] args) {
		try {
			//连接服务端
			Socket socket = new Socket("127.0.0.1",8088);
			//获取输出流
			OutputStream out = socket.getOutputStream();
			//创建SAXReader
			SAXReader reader = new SAXReader();
			//读取指定文件
			Document doc = reader.read(new File("EmpList.xml"));
			//创建XML输出流
			XMLWriter writer = new XMLWriter();
			writer.setOutputStream(out);
			writer.write(doc);		
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}