Java程序设计--XML、设计模式(二十一)


1、XML

1.1 XML概述

XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。

XML的几个特点和使用场景

  • 一是纯文本,默认使用UTF-8编码;二是可嵌套
  • 如果把XML内容存为文件,那么它就是一个XML文件
  • XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息

1.2 XML的创建、语法规则

XML的创建就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.xml

在这里插入图片描述
XML丽借法规则

  • XML文件的后缀名为: xml
  • 文档声明必须是第一行
    在这里插入图片描述
    XML的标签(元素)规则
  • 标签由一对尖括号和合法标识符组成:< name >< /name >,必须存在一个根标签,有且只能有一个。
  • 标签必须成对出现,有开始,有结束: < name >< /name >
  • 特殊的标签可以不成对,但是必须有结束标记,如:< br/>
  • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来< /name >
  • 标签需要正确的嵌套

XML的其他组成

  • XML文件中可以定义注释信息:<!- -注释内容 - ->
  • XML文件中可以存在以下特殊字符
  • XML文件中可以存在CDATA区:<![CDATA[ ..内容...]]>

1.3 XML文档约束

文档约束:是用来限定xml文件中的标签以及属性应该怎么写。

DTD约束

  1. 编写DTD约束文档,后缀必须是.dtd
    在这里插入图片描述

  2. 在需要编写的XML文件中导入该DTD约束文档

  3. 按照约束的规定编写XML文件的内容

(不能约束具体的数据类型)

schema

  • schema可以约束具体的数据类型,约束能力上更强大
  • schema本身也是一个xml文件,本身也受到其他约束文件的要求,所以编写的更加严谨

在这里插入图片描述


2、XML解析技术

2.1 XML解析技术概述

XML解析就是使用程序读取XML中的数据

两种解析方式

  • SAX解析
  • DOM解析

Dom常见的解析工具

名称说明
JAXPSUN公司提供的一套XML的解析的API
JDOMJDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
dom4j是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。
jsoup功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便

在这里插入图片描述

2.2 Dom4J解析XML文件

使用Dom4J把一个XML文件的数据进行解析

  • 下载Dom4j框架,官网下载
  • 在项目中创建一个文件夹:lib
  • 将dom4j-2.1.1.jar文件复制到lib文件夹
  • 在jar文件上点右键,选择Add as Library ->点击OK
  • 在类中导包使用
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

/**
   目标:学会使用dom4j解析XML文件中的数据。
    1、导入dom4j框架。
    2、准备一个XML文件。
 */
public class Dom4JHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws Exception {
        // 1、创建一个Dom4j的解析器对象,代表了整个dom4j框架
        SAXReader saxReader = new SAXReader();

        // 2、把XML文件加载到内存中成为一个Document文档对象
        // Document document = saxReader.read(new File("xml-app\\src\\Contacts.xml")); // 需要通过模块名去定位
        // Document document = saxReader.read(new FileInputStream("xml-app\\src\\Contacts.xml"));

        // 注意: getResourceAsStream中的/是直接去src下寻找的文件
        InputStream is = Dom4JHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);

        // 3、获取根元素对象
        Element root = document.getRootElement();
        System.out.println(root.getName());

        // 4、拿根元素下的全部子元素对象(一级)
        // List<Element> sonEles =  root.elements();
        List<Element> sonEles =  root.elements("contact");
        for (Element sonEle : sonEles) {
            System.out.println(sonEle.getName());
        }

        // 拿某个子元素
        Element userEle = root.element("user");
        System.out.println(userEle.getName());

        // 默认提取第一个子元素对象 (Java语言。)
        Element contact = root.element("contact");
        // 获取子元素文本
        System.out.println(contact.elementText("name"));
        // 去掉前后空格
        System.out.println(contact.elementTextTrim("name"));
        // 获取当前元素下的子元素对象
        Element email = contact.element("email");
        System.out.println(email.getText());
        // 去掉前后空格
        System.out.println(email.getTextTrim());

        // 根据元素获取属性值
        Attribute idAttr = contact.attribute("id");
        System.out.println(idAttr.getName() + "-->" + idAttr.getValue());
        // 直接提取属性值
        System.out.println(contact.attributeValue("id"));
        System.out.println(contact.attributeValue("vip"));
    }
}

Dom4j解析XML-得到Document对象,从中获取元素对象和内容。

SAXReader类

构造器/方法说明
public SAXReader()创建Dom4J的解析器对象
Document read(String url)加载XML文件成为Document对象

Document类

方法名说明
Element getRootElement()获得根元素对象

Dom4j解析XML的元素、属性、文本

方法名说明
List< Element > elements()得到当前元素下所有子元素
List< Element > elements(String name)得到当前元素下指定名字的子元素返回集合
Element element(String name)得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
String getName()得到元素名字
String attributeValue(String name)通过属性名直接得到属性值
String elementText(子元素名)得到指定名称的子元素的文本
String getText()得到文本

3、XML检索技术

XPath介绍

  • XPath在解析XML文档方面提供了一独树一帜的路径思想,更加优雅,高效
  • XPath使用路径表达式来定位XML文档中的元素节点或属性节点。

使用Xpath检索出XML文件

  1. 导入jar包(dom4j和jaxen-1.1.2.jar),Xpath技术依赖Dom4j技术
  2. 通过dom4j的SAXReader获取Document对象
  3. 利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作。
  4. Document中与Xpath相关的API如下:
方法名说明
Node selectSingleNode(“表达式”)获取符合表达式的唯一元素
List< Node > selectNodes(“表达式”)获取符合表达式的元素集合

XPath:绝对路径

采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息

方法名说明
/根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级

XPath:相对路径

先得到根节点contactList,再采用相对路径获取下一级contact节点的name子节点并打印信息

方法名说明
./子元素/孙元素从当前元素开始,一级一级向下查找,不能跨级

XPath:全文搜索

·
直接全文搜索所有的name元素并打印

方法名说明
//contact找contact元素,无论元素在哪里
//contact/name找contact,无论在哪一级,但name一定是contact的子节点
//contact//namecontact无论在哪一种,name只要是contact的子孙元素都可以找到

XPath:属性查找

在全文中搜索属性,或者带属性的元素

方法名说明
//@属性名查找属性对象,无论是哪个元素,只要有这个属性即可。
//元素[@属性名]查找元素对象,全文搜索指定元素名和属性名。
//元素//@属性名=‘值’]查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.List;

public class XPathDemo {
    /**
     1.绝对路径: /根元素/子元素/子元素。
     */
    @Test
    public void parse01() throws Exception {
        // a、创建解析器对象
        SAXReader saxReader = new SAXReader();
        // b、把XML加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        // c、检索全部的名称
        List<Node> nameNodes = document.selectNodes("/contactList/contact/name");
        for (Node nameNode : nameNodes) {
            Element  nameEle = (Element) nameNode;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     2.相对路径: ./子元素/子元素。 (.代表了当前元素)
     */
    @Test
    public void parse02() throws Exception {
        // a、创建解析器对象
        SAXReader saxReader = new SAXReader();
        // b、把XML加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        Element root = document.getRootElement();
        // c、检索全部的名称
        List<Node> nameNodes = root.selectNodes("./contact/name");
        for (Node nameNode : nameNodes) {
            Element  nameEle = (Element) nameNode;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     3.全文搜索:
     //元素  在全文找这个元素
     //元素1/元素2  在全文找元素1下面的一级元素2
     //元素1//元素2  在全文找元素1下面的全部元素2
     */
    @Test
    public void parse03() throws Exception {
        // a、创建解析器对象
        SAXReader saxReader = new SAXReader();
        // b、把XML加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        // c、检索数据
        //List<Node> nameNodes = document.selectNodes("//name");
        // List<Node> nameNodes = document.selectNodes("//contact/name");
        List<Node> nameNodes = document.selectNodes("//contact//name");
        for (Node nameNode : nameNodes) {
            Element  nameEle = (Element) nameNode;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     4.属性查找。
     //@属性名称  在全文检索属性对象。
     //元素[@属性名称]  在全文检索包含该属性的元素对象。
     //元素[@属性名称=值]  在全文检索包含该属性的元素且属性值为该值的元素对象。
     */
    @Test
    public void parse04() throws Exception {
        // a、创建解析器对象
        SAXReader saxReader = new SAXReader();
        // b、把XML加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        // c、检索数据
        List<Node> nodes = document.selectNodes("//@id");
        for (Node node : nodes) {
            Attribute attr = (Attribute) node;
            System.out.println(attr.getName() + "===>" + attr.getValue());
        }

        // 查询name元素(包含id属性的)
//      Node node = document.selectSingleNode("//name[@id]");
        Node node = document.selectSingleNode("//name[@id=888]");
        Element ele = (Element) node;
        System.out.println(ele.getTextTrim());
    }
}


4、设计模式

4.1 工厂模式

工厂模式(Factory Pattern)是Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。

工厂设计模式的作用:

  1. 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入。
  2. 可以实现类与类之间的解耦操作(核心思想)。
public abstract class Computer {
    private String name;
    private double price;

    public abstract void start();

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}


public class Huawei extends Computer{
    @Override
    public void start() {
        System.out.println(getName() + "开机了,展示了华为的菊花图标~~~~");
    }
}

public class Mac extends Computer{
    @Override
    public void start() {
        System.out.println(getName() + "以非常优雅的方法启动了,展示了一个苹果logo");
    }
}
public class FactoryPattern {
    /**
       定义一个方法,创建对象返回
     */
    public static Computer createComputer(String info){
        switch (info){
            case "huawei":
                Computer c = new Huawei();
                c.setName("huawei pro 16");
                c.setPrice(5999);
                return c;
            case "mac":
                Computer c2 = new Mac();
                c2.setName("MacBook pro");
                c2.setPrice(11999);
                return c2;
            default:
                return null;
        }
    }
}

public class FactoryDemo {
    public static void main(String[] args) {
        Computer c1 = FactoryPattern.createComputer("huawei");
        c1.start();

        Computer c2 = FactoryPattern.createComputer("mac");
        c2.start();
    }
}

4.2 装饰模式

装饰设计模式是创建一个新类,包装原始类,从而在新类中提升原来类的功能。

装饰设计模式的作用:

作用:装饰模式指的是在不改变原类的基础上,动态地扩展─个类的功能。

  1. 定义父类
  2. 定义原始类,继承父类,定义功能。
  3. 定义装饰类,继承父类,包装原始类,增强功能!!
/**
   共同父类
 */
public abstract class InputStream {
    public abstract int read();
    public abstract int read(byte[] buffer);
}

import java.util.Arrays;

/**
   原始类
 */
public class FileInputStream extends InputStream{
    @Override
    public int read() {
        System.out.println("低性能的方式读取了一个字节a");
        return 97;
    }

    @Override
    public int read(byte[] buffer) {
        buffer[0] = 97;
        buffer[1] = 98;
        buffer[2] = 99;
        System.out.println("低性能的方式读取了一个字节数组:" + Arrays.toString(buffer));
        return 3;
    }
}

/**
   装饰类:继承InputStream 拓展原始类的功能
 */
public class BufferedInputStream extends InputStream{
    private InputStream is;
    public BufferedInputStream(InputStream is){
        this.is = is;
    }
    @Override
    public int read() {
        System.out.println("提供8KB的缓冲区,提高读数据性能~~~~");
        return is.read();
    }

    @Override
    public int read(byte[] buffer) {
        System.out.println("提供8KB的缓冲区,提高读数据性能~~~~");
        return is.read(buffer);
    }
}

/**
  装饰模式

    定义父类:InputStream
    定义实现类:FileInputStream 继续父类 定义功能
    定义装饰实现类:BufferedInputStream 继承父类 定义功能 包装原始类,增强功能。
 */
public class DecoratorPattern {
    public static void main(String[] args) {
        InputStream is = new BufferedInputStream(new FileInputStream());
        System.out.println(is.read());
        System.out.println(is.read(new byte[3]));
    }
}



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java 可以使用 DOM(文档对象模型)或 SAX(简单 API for XML)等 API 来编 XML。 使用 DOM 编 XML: 1. 创建 Document 对象,作为 XML 文档的根节点。 2. 创建 Element 对象,作为 XML 文档的元素节点。 3. 将 Element 对象添加到 Document 对象中。 4. 创建属性节点并将其添加到 Element 对象中。 5. 创建文本节点并将其添加到 Element 对象中。 6. 将 Element 对象添加到父节点中。 7. 将 Document 对象入到 XML 文件中。 示例代码: ```java import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; public class WriteXML { public static void main(String[] args) throws Exception { // 创建 DocumentBuilder 对象 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); // 创建 Document 对象 Document doc = builder.newDocument(); // 创建根节点 Element root = doc.createElement("Books"); doc.appendChild(root); // 创建子节点 Element book = doc.createElement("Book"); book.setAttribute("id", "001"); root.appendChild(book); Element title = doc.createElement("Title"); title.appendChild(doc.createTextNode("Java Programming")); book.appendChild(title); Element author = doc.createElement("Author"); author.appendChild(doc.createTextNode("John Smith")); book.appendChild(author); Element price = doc.createElement("Price"); price.appendChild(doc.createTextNode("29.99")); book.appendChild(price); // 将 Document 对象入到 XML 文件中 TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult("books.xml"); transformer.transform(source, result); } } ``` 使用 SAX 编 XML: 1. 创建 SAXParserFactory 对象。 2. 创建 SAXParser 对象。 3. 自定义 Handler 类,并实现相应的回调方法。 4. 将 Handler 对象注册到 SAXParser 中。 5. 解析 XML 文件。 示例代码: ```java import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class WriteXML { public static void main(String[] args) throws Exception { // 创建 SAXParser 对象 SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); // 创建 Handler 对象 MyHandler handler = new MyHandler(); // 将 Handler 对象注册到 SAXParser 中 parser.parse("books.xml", handler); } } class MyHandler extends DefaultHandler { private String currentElement; private String title; private String author; private String price; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { currentElement = qName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { String value = new String(ch, start, length).trim(); if (value.length() == 0) { return; } switch (currentElement) { case "Title": title = value; break; case "Author": author = value; break; case "Price": price = value; break; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("Book")) { System.out.println("Title: " + title); System.out.println("Author: " + author); System.out.println("Price: " + price); } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会思想的苇草i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值