实验六 XML文档的验证、解析和转换
一、实验目的
通过本实验,了解SAX和DOM解析原理,能够使用JAXP接口完成对XML文档的解析和转换。
二、实验条件
配置有windows记事本、写字板 或 XMLSpy开发环境以及Java开发环境的计算机设备。
三、实验原理及相关知识
(1)XML文档语法规范和DTD验证
(2)DOM和SAX解析原理及Java编程对XML文档进行解析
(3)使用XSLT和XPath完成从XML文档到HTML格式的转换
四、实验内容及步骤
第一部分:
XML文档(students.xml)如下:
<?xml version="1.0" encoding="GB2312"?>
<students>
<student sn="01">
<name>张三</name>
<age>18</age>
</student>
<student sn="02">
<name>李四</name>
<age>20</age>
</student>
<student sn="03">
<name>王五</name>
<age>21</age>
</student>
</students>
编写五个独立的java程序解析该xml文档,分别完成以下五个要求:
- 输出所有学生的编号(sn)、姓名(name)和年龄(age);
import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class DOMStudentsInfo { public static void main(String[] args) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); File file = new File("students.xml"); Document doc = (Document) db.parse(file); NodeList nl = doc.getElementsByTagName("student"); int len = nl.getLength(); for (int i = 0; i < len; i++) { Element eltStu = (Element) nl.item(i); Node eltName = eltStu.getElementsByTagName("name").item(0); Node eltAge =eltStu.getElementsByTagName("age").item(0); String name = eltName.getFirstChild().getNodeValue(); String age = eltAge.getFirstChild().getNodeValue(); System.out.println("-----------------学生信息-----------------"); System.out.println("学号:"+eltStu.getAttribute("sn")); System.out.println("姓名:"+name); System.out.println("年龄:"+age); System.out.println(); } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
-
查询姓名(name)为“李四”的学生的年龄并输出;
package xmltest2; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class test2 { public static void main(String[] args) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); File file = new File("students.xml"); Document doc = (Document) db.parse(file); NodeList nl = doc.getElementsByTagName("student"); int len = nl.getLength(); for (int i = 0; i < len; i++) { Element eltStu = (Element) nl.item(i); Node eltName = eltStu.getElementsByTagName("name").item(0); Node eltAge =eltStu.getElementsByTagName("age").item(0); String name = eltName.getFirstChild().getNodeValue(); String age = eltAge.getFirstChild().getNodeValue(); if(name.equals("李四")) { System.out.println("李四的年龄为:"+age); break; } else { continue; } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
- 查询编号(sn)为“02”的学生的姓名(name)和年龄(age)并输出;
package test3; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class test3 { public static void main(String[] args) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); File file = new File("students.xml"); Document doc = (Document) db.parse(file); NodeList nl = doc.getElementsByTagName("student"); int len = nl.getLength(); for (int i = 0; i < len; i++) { Element eltStu = (Element) nl.item(i); Node eltName = eltStu.getElementsByTagName("name").item(0); Node eltAge =eltStu.getElementsByTagName("age").item(0); String name = eltName.getFirstChild().getNodeValue(); String age = eltAge.getFirstChild().getNodeValue(); if(eltStu.getAttribute("sn").equals("02")) { System.out.println("姓名:"+name); System.out.println("年龄:"+age); break; } else { continue; } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
- 删除姓名(name)为“李四”的学生,保存为新的xml文档并输出新文档中所有学生的姓名(name)和年龄(age);
import java.io.File; import java.io.IOException; import javax.xml.parsers.*; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.*; import org.xml.sax.SAXException; public class test4 { public static void main(String[] args) { int delnum=0; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("students.xml")); NodeList nl = doc.getElementsByTagName("student"); for (int i = 0; i < nl.getLength(); i++) { Element elt = (Element) nl.item(i); Node nodeName = elt.getElementsByTagName("name").item(0); String name0 = nodeName.getFirstChild().getNodeValue(); if(name0.equals("李四")) { delnum=i;//获得名为李四的学生的索引值 break; } else { continue; } } Node nodeDel = nl.item(delnum); nodeDel.getParentNode().removeChild(nodeDel); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File("converted.xml")); TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); tf.setOutputProperty(OutputKeys.ENCODING, "gb2312"); tf.transform(source, result); Document doc1 = db.parse(new File("converted.xml")); NodeList nl1 = doc1.getElementsByTagName("student"); for (int j = 0; j < nl.getLength(); j++) { Element elt1 = (Element) nl1.item(j); Node nodeName = elt1.getElementsByTagName("name").item(0); Node nodeAge = elt1.getElementsByTagName("age").item(0); String name1 = nodeName.getFirstChild().getNodeValue(); String age1 = nodeAge.getFirstChild().getNodeValue(); System.out.println("-----------------学生信息-----------------"); System.out.println("学号:" + elt1.getAttribute("sn")); System.out.println("姓名:"+name1); System.out.println("年龄:"+age1); System.out.println(); } } catch (ParserConfigurationException e){e.printStackTrace();} catch (SAXException e){e.printStackTrace();} catch (IOException e){e.printStackTrace();} catch (TransformerConfigurationException e){e.printStackTrace();} catch (TransformerException e){e.printStackTrace();} } }
- 修改编号(sn)为“01”的学生年龄为21,保存为新的xml文档并输出新文档中所有学生的编号(sn)、姓名(name)和年龄(age) ;
import java.io.File; import java.io.IOException; import javax.xml.parsers.*; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.*; import org.xml.sax.SAXException; public class test5 { public static void main(String[] args) { int altnum=0; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("students.xml")); NodeList nl = doc.getElementsByTagName("student"); for (int i = 0; i < nl.getLength(); i++) { Element elt = (Element) nl.item(i); if(elt.getAttribute("sn").equals("01")) { altnum=i;//获得名为李四的学生的索引值 break; } else { continue; } } Element eltChg = (Element) nl.item(altnum); Node nodeAgeChg = eltChg.getElementsByTagName("age").item(altnum); nodeAgeChg.getFirstChild().setNodeValue("21"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File("converted1.xml")); TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); tf.setOutputProperty(OutputKeys.ENCODING, "gb2312");//避免乱码 tf.transform(source, result); Document doc1 = db.parse(new File("converted1.xml")); NodeList nl1 = doc1.getElementsByTagName("student"); for (int i = 0; i < nl1.getLength(); i++) { Element elt1 = (Element) nl1.item(i); Node nodeName = elt1.getElementsByTagName("name").item(0); Node nodeAge = elt1.getElementsByTagName("age").item(0); String name1 = nodeName.getFirstChild().getNodeValue(); String age1 = nodeAge.getFirstChild().getNodeValue(); System.out.println("-----------------学生信息-----------------"); System.out.println("学号:"+elt1.getAttribute("sn")); System.out.println("姓名:"+name1); System.out.println("年龄:"+age1); System.out.println(); } } catch (ParserConfigurationException e){e.printStackTrace();} catch (SAXException e){e.printStackTrace();} catch (IOException e){e.printStackTrace();} catch (TransformerConfigurationException e){e.printStackTrace();} catch (TransformerException e){e.printStackTrace();} } }
第二部分(选做):
1、编写XML文档约束
根据下图中显示的信息,编写一个DTD文档,其内容要求能够包含图中所有的信息点。图中所包含的信息点进行如下说明:
要求编写的DTD文档用来约束一个保存书籍信息的XML文档;
书分为中文原版和外文翻译两种情况,两种不同类型的书都应该具有“书名”、“评价”、“作者”、“书号”、“丛书名”、“出版社”、“开本”、“出版日期”、“页码”、“版次”的记录项、而对于外文翻译类型的书要额外具有“原书名”、“译者”和“原出版社”的记录项。
元素名和属性名建议使用有意义的英文字符串来命名。
在编写DTD时,有些难以协调的地方可以忽略,以保证必要信息为原则进行设计。
testdtd.dtd:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT Bookinfo (Book*)>
<!ELEMENT Book (name,evaluation,author,bnum,sname,phouse,bsize,pdate,pnum,edition,category?,ori?)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT evaluation (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT bnum (#PCDATA)>
<!ELEMENT sname (#PCDATA)>
<!ELEMENT phouse (#PCDATA)>
<!ELEMENT bsize (#PCDATA)>
<!ELEMENT pdate (#PCDATA)>
<!ELEMENT pnum (#PCDATA)>
<!ELEMENT edition (#PCDATA)>
<!ELEMENT category (#PCDATA)>
<!ELEMENT ori (ori_name,translator,ori_phouse)>
<!ELEMENT ori_name (#PCDATA)>
<!ELEMENT translator (#PCDATA)>
<!ELEMENT ori_phouse (#PCDATA)>
2、编写一个XML文档,使其在DTD约束下是有效的
假设上一步编写的DTD文档文件名为:testdtd.dtd,编写一个XML文档使其在test.dtd文件的约束下成为一个有效的XML文档。然后,对你编写的XML文档进行有效性验证。
test.xml:
在DTD下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Bookinfo SYSTEM "F:\测试\XML\testdtd.dtd">
<Bookinfo>
<Book>
<name>数据恢复技术(第2版)</name>
<evaluation>三星半</evaluation>
<author>戴士剑 徐彦晖</author>
<bnum>7-121-00756-8</bnum>
<sname>安全技术大系</sname>
<phouse>电子工业出版社</phouse>
<bsize>16开</bsize>
<pdate>2005-3-1</pdate>
<pnum>711</pnum>
<edition>2-1</edition>
<category>计算机>安全>数据安全</category>
</Book>
<Book>
<name>SQL Server2005从入门到精通(应用技术基础)</name>
<evaluation>两星半</evaluation>
<author>(美)Solid Quality Learning</author>
<bnum>7-302-13801-X</bnum>
<sname>微软技术丛书</sname>
<phouse>清华大学出版社</phouse>
<bsize>185*260</bsize>
<pdate>2006-9-1</pdate>
<pnum>280</pnum>
<edition>1-1</edition>
<ori>
<ori_name>Microsoft SQL Server2005 Applied Techniques Step by Step</ori_name>
<translator>王为</translator>
<ori_phouse>Microsoft Press</ori_phouse>
</ori>
</Book>
</Bookinfo>