《Java核心技术 卷II》笔记——(8)XML解析

XML?

XML(EXtensible Markup Language),可扩展标记语言;

区别于java.util.Properties,将配置信息保存在“属性文件”中,以便读取和修改;(Properties文件下的属性-描述难以解析,与文本长度/格式有关)

XML的特点?

  1. XML与操作系统、编程语言的开发平台都无关【通用的数据交换格式】

  2. 实现不同系统之间的数据交换【包括系统的配置文件】

  3. 是一种标记语言,没有固定的标记,可以随便发明也可以自己创建

  4. 【整个XML是一种树形文件】

XML有什么用?

  1. 数据交互
  2. 配置应用程序和网站
  3. Ajax基石

XML怎么写(结构是什么样)?

  • 开头 - <?xml version="1.0"?> 【声明部分(位于第一行);这个是满足xml 1.0标准的】
  • 文档类型定义 - <!DOCTYPE web-app PUBLIC ...>
  • 正文(包括 根元素/其他元素/文本) - <A0> <A1>...</A1> <A0>
    【底下的都是:文档元素描述信息(文档结构),所有带尖括号的都叫标签,也叫元素,都是用树形文件写出来的】

eg:

<?xml version="1.0" encoding="UTF-8"?>    
<books>    【根元素,每个XML文件的根元素有且仅有一个】
    <!--图书信息 -->       【XML中的注释语法:<!--……-->】
    <book id="bk101">     【books的子元素,包含关系的元素要用缩进来体现】
        <author>王珊</author>     【book的子元素】
        <title>.NET高级编程</title>   【就像以前的类和属性】
        <description>包含C#框架和网络编程等</description>
    </book>
    <book id="bk102">    【books的子元素】
        <author>李明明</author>
        <title>XML基础编程</title>
        <description>包含XML基础概念和基本作用</description>
    </book>
</books>    【根元素</……>是结束的符号】

XML的语法

  1. 属性值用双引号包裹,eg:<book id="bk101">
  2. 一个元素可以有多个属性(或者叫子元素),eg:book元素下的<author><title><description>
  3. 属性值中不能直接包含<、“、&(不建议:‘、>)【最好都不要写】

XML写法小结

  1. XML文档内容由一系列标签元素组成,XML必须正确的嵌套,所有XML元素都必须有结束标签(</……>);
  2. 根元素有且仅有一个;
  3. <元素名 属性名=“属性值”>元素内容</元素名>,同级标签以缩进对齐;
  4. XML标签对大小写敏感;
  5. 空元素的方法:
    <name>(这里是一个空格)</name>
    <name></name>
    <name/>
  6. 当元素中出现很多特殊字符时,可以使用CDATA节,如:<description><![CDATA[讲解了元素<title>以及</title>的使用]]> 等同于:<description><讲解了元素<title>以及</title>的使用> </description>
  7. 为解决命名冲突,采取了类似Java包 (com.myStudy.test) 的方式,即“命名空间 namespace”,eg:
<element xmlns:="namespace_URL01" >
    <child xmlns:="namespace_URL02">
    grand_children
    </child>
    more_children ...
</element>

元素命名习惯?

  1. 编写的元素名称要有描述性,元素名称可以包含字母、数字或其他的字符,元素名称不能以数字或者标点符号开始(<5name>是错误的);
  2. 名字尽量简短些,可以用下划线“_”,但是不要用中横线“-”、点“.”或者冒号“:”(<book_title>);
  3. 数据库怎么命名,XML文件就怎么命名,要保持一致;

XML解析?

要处理XML文档,先得要解析(parse)它;解析器:读入一个文件,确认这个文件有正确的格式,然后将其分解成各种元素,然后可以访问这些元素;

Java库提供了两种解析器:DOMSAX

解析XML的相关技术?

  • DOM

基于XML文档树结构的解析(DOM把XML文档映射成一个倒挂的树,解析成DOM树放内存里)
适用于多次访问的XML文档
特点:比较消耗资源

DOM解析XML文件步骤?

  1. 创建解析器工厂对象
  2. 解析器工厂对象创建解析器对象
  3. 解析器对象指定XML文件创建Document对象
  4. 以Document对象为起点操作DOM树

eg:下面的“(读)写XML文件?”中给出了Document对象的使用示例;

  • SAX

基于事件的解析,适用于大数据量的XML文档
特点:占用资源少,内存消耗小

  • DOM4J(把DOM解析进行了一次封装,应用更多)

非常优秀的Java XML API;
性能优异、功能强大;
开放源代码;

XML与反射?

eg:web.xml的Servlet配置,读取xml文件,根据名称获取server下的子元素,通过ClassForName反射获取类信息,newInstance得到对象,invoke()调用对象方法;

定义一个接口,有a() b() c()3个方法;将其实现类放在xml的Servlet配置里面(类名、路径)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<servlet>
    <servlet-name>MyServer</servlet-name>
    <servlet-class>com.oracle.demo04.PersonS</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServer</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
//test

@Test
public void fuc_02() throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, DocumentException {
    //创建解析器
 SAXReader sa = new SAXReader();
 //此处写要读取xml文件的路径
 Document doc = (Document) sa.read("testXML\\xml_01.xml");
 //获取根元素<web-app>
 Element el = doc.getRootElement();
 //获取根元素下的指定的子元素
 Element em = el.element("servlet");
 //获取server下的子元素
 String servletclass = em.elementText("servlet-class");
 //获取后再根据获取到的xml元素来获取字节码对象
 Class c = Class.forName(servletclass);
 //创建一个对象,然后通过字节码对象来过去该类的方法
 Object obj = c.newInstance();
 Method a = c.getMethod("a");
 Method b = c.getMethod("b");
 Method c = c.getMethod("c");
 //调用方法
 a.invoke(obj);
 b.invoke(obj);
 c.invoke(obj);
 //要注意,xml的路径一定要写对,创建doc对象读取的路径也要写对
}

(读)写XML文件?

对XML文件的元素“增删改查”;

eg:XML源文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<exam>
    <student examid="111" idcard="123">
    <name>张三</name>
    <location>广州</location>
    <grade>100</grade>
</student>
<student examid="444" idcard="333">
    <name>李四</name>
    <location>大连</location>
    <grade>97</grade>
</student>
<student examid="1111111" idcard="22222">
    <name>小毛</name>
    <location>广州</location>
    <grade>23.0</grade>
</student>

<student examid="199" idcard="300">
    <grade>80.0</grade>
    <location>广州</location>
    <name>钟源茂</name>
</student>
</exam>

// test 用到getDocument()方法;删除和新增会用到writeXml(Document document),将内存数据保存至XML;如下所示:

// 获得操作xml文件的Document 对象

private static Document getDocument() throws ParserConfigurationException,
 IOException, org.xml.sax.SAXException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document document = builder.parse(new File("testXML\\xml_03.xml"));
    Element e = document.getDocumentElement();
    return document;
}
// 将内存中的数据保存到XML文件中
private static void writeXml(Document document) throws TransformerException {
    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(new File("testXML\\xml_03.xml"));
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer trans = factory.newTransformer();
    trans.transform(source, result);
}
1.读XML-查找:获取Doucument对象(绑定XML文件),根据TagName查找获得List元素列表,遍历列表获取各个元素属性来一一匹配目标值,找到后封装属性于返回对象;

public Student fuc_03(String Find_examid) throws IOException, SAXException, ParserConfigurationException {
    Document document = getDocument();
 NodeList list = document.getElementsByTagName("student");
 for (int i = 0; i < list.getLength(); i++) {
        Element element = (Element) list.item(i);
        String value = element.getAttribute("examid");
        if (Find_examid.equals(value)) {//遍历所有节点找到索引examid元素,如果其值value匹配Find_examid,则封装属性到Student对象返回
        Student student = new Student();
        student.setExamid(Find_examid);
        student.setIdcart(element.getAttribute("idcard"));
        student.setName(element.getElementsByTagName("name").item(0).getTextContent());
        student.setLocation(element.getElementsByTagName("location").item(0).getTextContent());
        student.setGrade(element.getElementsByTagName("grade").item(0).getTextContent());
        return student;
        }
    }
    return null;
}
2.新增:获取Doucument对象(绑定XML文件),document.createElement创建元素与其子元素,setAttribute和setTextContent添加元素属性,appendChild将子元素与父元素"绑定"-将父元素与根元素绑定,writeXml写入XML;

@Test
public void fuc_04() throws ParserConfigurationException,
 IOException, org.xml.sax.SAXException, TransformerException {
    Student student = new Student("明凯", "4396", "666", "武汉", "99");//test
    Document document = getDocument();//获得document对象
    Element studentNode = document.createElement("student");//新建Element元素对象
    studentNode.setAttribute("idcard", student.getIdcart());//设置“属性”值
    studentNode.setAttribute("examid", student.getExamid());
    Node name = document.createElement("name");//创建3个子Node并赋值
    name.setTextContent(student.getName());
    Node location = document.createElement("location");
    location.setTextContent(student.getLocation());
    Node grade = document.createElement("grade");
    grade.setTextContent(student.getGrade());
    // 将3个子元素添加到当前元素(绑定)
    studentNode.appendChild(name);
    studentNode.appendChild(location);
    studentNode.appendChild(grade);
    // 获取XML文档的根元素,将当前元素添加到其子元素列表中
    Element root = document.getDocumentElement();
    root.appendChild(studentNode);
    writeXml(document); // 将Document写入XML
}
3.删除,获取Doucument对象(绑定XML文件),查找目标元素node(根1.查找一样),removeChild()从 “根元素”/其父元素的“父元素” 删除其父元素,writeXml写入XML;

// 如:根据name删除整个元素,即从name找到其“父元素”,从 “根元素”/其父元素的“父元素” 删除其父元素

@Test
public void fuc_05() throws ParserConfigurationException, IOException, TransformerException, org.xml.sax.SAXException {
    String name = "钟源茂0";
    Document document = getDocument();
    NodeList list = document.getElementsByTagName("name");
    for (int i = 0; i < list.getLength(); i++) {
        Node node = list.item(i);
        if (node.getTextContent().equals(name)) {
            node.getParentNode().getParentNode().removeChild(node.getParentNode());//从当前name元素的父元素的“父元素” 删除其父元素
        }
    }
    writeXml(document);
}

XPath定位?

通过遍历DOM树需要从根节点开始查找节点,XPath可以指定“路径”,让元素/属性的访问变得容易;使用方法类似打开文件的目录一样;可以指定元素/exam/student、元素下的属性/exam/student/name(子元素)、元素列表下的某一个/exam/student[7]/name(按照索引)

eg:

// 测试XPath
@Test
public void fuc_06() throws ParserConfigurationException, IOException, TransformerException, org.xml.sax.SAXException, XPathExpressionException { 
  XPathFactory xPathFactory = XPathFactory.newInstance();
  XPath path = xPathFactory.newXPath();
  Document document = getDocument();//获得document对象
  NodeList list = (NodeList) (path.evaluate("/exam/student/name", document, XPathConstants.NODESET));//满足指定路径Path的整个列表
  for (int i = 0; i < list.getLength(); i++) {
    System.out.println(list.item(i).getTextContent());
  }
  Node node_01 = (Node) (path.evaluate("/exam/student[1]/name", document, XPathConstants.NODE));//满足指定路径Path的第1个元素(从1开始)
  System.out.println("node_01:"+node_01.getTextContent());
  String node_02 = (String) (path.evaluate("/exam/student[2]/name", document, XPathConstants.STRING));//ke==可以直接转成String/int/boolean...
  System.out.println("node_02:"+node_02);
}

流机制解析器?

DOM会完整的读入XML文档形成一个树形结构;如果文档太大,DOM的效率就不高,这种情况下就可以使用“流机制解析器”在运行时解析节点,如SAX解析器;

得到SAX解析器:
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();

处理文档:saxParser.parse(source, handler); source是数据源(文件、URL、输入流);handler是处理器,为DefaultHandler类的对象(实现startElement方法);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文件上传是Web开发中常见的功能之一,Java中也提供了多种方式来实现文件上传。其中,一种常用的方式是通过Apache的commons-fileupload组件来实现文件上传。 以下是实现文件上传的步骤: 1.在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency> ``` 2.在前端页面中添加文件上传表单: ```html <form method="post" enctype="multipart/form-data" action="upload"> <input type="file" name="file"> <input type="submit" value="Upload"> </form> ``` 3.在后台Java代码中处理上传文件: ```java // 创建一个DiskFileItemFactory对象,用于解析上传的文件 DiskFileItemFactory factory = new DiskFileItemFactory(); // 设置缓冲区大小,如果上传的文件大于缓冲区大小,则先将文件保存到临时文件中,再进行处理 factory.setSizeThreshold(1024 * 1024); // 创建一个ServletFileUpload对象,用于解析上传的文件 ServletFileUpload upload = new ServletFileUpload(factory); // 设置上传文件的大小限制,这里设置为10MB upload.setFileSizeMax(10 * 1024 * 1024); // 解析上传的文件,得到一个FileItem的List集合 List<FileItem> items = upload.parseRequest(request); // 遍历FileItem的List集合,处理上传的文件 for (FileItem item : items) { // 判断当前FileItem是否为上传的文件 if (!item.isFormField()) { // 获取上传文件的文件名 String fileName = item.getName(); // 创建一个File对象,用于保存上传的文件 File file = new File("D:/uploads/" + fileName); // 将上传的文件保存到指定的目录中 item.write(file); } } ``` 以上代码中,首先创建了一个DiskFileItemFactory对象,用于解析上传的文件。然后设置了缓冲区大小和上传文件的大小限制。接着创建一个ServletFileUpload对象,用于解析上传的文件。最后遍历FileItem的List集合,判断当前FileItem是否为上传的文件,如果是,则获取文件名,创建一个File对象,将上传的文件保存到指定的目录中。 4.文件上传完成后,可以给用户一个提示信息,例如: ```java response.getWriter().write("File uploaded successfully!"); ``` 以上就是使用Apache的commons-fileupload组件实现文件上传的步骤。需要注意的是,文件上传可能会带来安全隐患,因此在处理上传的文件时,需要进行严格的校验和过滤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值