网站首页 > java教程 正文
在实际项目中我们经常会需要用到垮平台通讯的情况,支持跨平台通讯的技术很多,用到的通讯使用的文本格式也很多,例如JSON和XML等。在这里浅谈下对XML的认识和简单的解析。
XML:可扩展的标记语言;Extend Markup Language,是以标记和子标记的方法描述对象,集合。例如我们现在有这么一个实体类

public class Stutent {
    
    private int id;
    private String name;
    private String sex;
}那么我们用XML文件可以这么表示
<?xml version="1.0" encoding="utf-8"?>
<Students>
      <student id="1">
            <name>张三</name>
            <sex>男</sex>
      </student>
      <student id="2">
            <name>李四</name>
            <sex>女</sex>
      </student>
      <student id="3">
            <name>王五</name>
            <sex>男</sex>
      </student>
</Students>一个标准的XML的组成格式
--version --文档符合XML 1.0规范,现在只有1.0
--encoding-- 文档字符编码,默认为“UTF-8”
-- standalone-- 文档定义是否在一个文件内(没有DTD可以不定义)
* stanalond="yes"
* stanalone="no"<?xml version="1.0" encoding="utf-8" stanalone="no">standalone 定义了外部定义的 DTD 文件的存在性,no 表示这个 XML 文档不是独立的而是依赖于外部所定义的一个 DTD. 值 yes 表示这个 XML 文档是自包含的(self-contained)
XML中的空元素,表示标签直接没有内容。例如现在我们的XML中有money这么个元素
<money></money>
<money?>   
XML根元素
* 每个XML文档必须有有且只有一个根元素
* 根元素是一个完全包括文档中的其他素有元素的元素
* 所有元素都必须在根元素中定义XML有严格的格式要求,对大小写和符号敏感,在XML中有有5个特殊符号需要转义需要注意的是:
- 转义序列各字符间不能有空格;
- 转义序列必须以";"结束;
- 单独的&不被认为是转义开始;
- 区分大小写。
&(逻辑与)  &       
<(小于)    <       
>(大于)    >       
"(双引号)  "     
'(单引号)  '如果不想用转义符,也可以使用CDATA标签,CDATA是不被解析的文件。文本内的标签不会被当做标记,实体不会被展开。
<![CDATA[
**********************
]]>
结构完整的XML文档满足XML基本的语法规则,如果XMML文档不是良好的格式,就不能被引用程序和浏览器正确识别和解析
语法规范
- 必须有XML声明语句
<?xml version="1.0" encoding="utf-8"?>2.必须有且只有一个根元素3.标记大小写敏感
- 属性值需用引号
- 标记成对
- 空标记记得关闭 <a/> <a></a>
- 元素正确嵌套
有效的XML有效的XML除了要满足XML规范外,还要满足相应的DTD和Schema定义的元素规则有效的XML一定是格式良好的,但是格式良好的XML不一定是有效的
DTD
<?xml version="1.0" encoding="GB2312" ?>
<!DOCTYPE 家庭 [                <!--DOCTYPE定义根元素:家庭-->
<!ELEMENT 家庭 (人+,家电*)>   <!--ELEMENT表示描述元素:()表示定义元素的子元素-->
<! ELEMENT 人 (#PCDATA)>     <!--#PCDATA表示"人"元素,标签中间的内容为文本-->
<!ELEMENT 家电 EMPTY>          <!--EMPTY表示"家电"元素为空元素-->
<!ATTLIST 人               <!--ATTLIST 表示定义元素的属性>
  名字 CDATA #REQUIRED     <!--CDATA 表示属性的内容为文本-->
  性别 (男|女) #REQUIRED     <!--#REQUIRED表示该属性必须书写-->
  年龄 CDATA #REQUIRED
  爱好 CDATA #IMPLIED          <!--#IMPLIED表示该属性可有可无-->
>
<!ATTLIST 家电
   名称 CDATA #REQUIRED
   数量 CDATA #REQUIRED
   说明 CDATA #IMPLIED
>
]>
XML的解析技术有很多种这里只列举了两种XML解析技术文档对象模型(DOM),一种基于树结构的APIDOM解析1.基于树状结构的API2.整个XML文档必须在内存中解析和存储3.客户端引用程序就可以随机访问这些对象
- 大型文档为造成内存紧张
XML简单(SAX),一种事件驱动APISAX1.SAX提供一种用于解析XML文档的事件驱动模型2.使用回调机制将事件通知应用程序
特点
- 不必将整个文件加载到内存中,占用内存少
- 不能对文档进行随机访问
- SAX是只读的
- 文档只能遍历一次
下面就基于SAX做一个简单的XML解析,这里我们用的dom4j这个jar来做解析
需要的jar
XML对应的实体Bean
package com.lovo.beans;
import java.io.Serializable;
/**
 * 测试用简单商品类
 * @author WZH
 *
 */
public class Product implements Serializable{
    private static final long serialVersionUID = 5801648617772990983L;
    
    //商品id
    private Long id;
    //商品名
    private String name;
    //商品价格
    private double price;
    //厂商
    private String factory;
    
    public Product() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    public Product(Long id, String name, double price, String factory) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
        this.factory = factory;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    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 String getFactory() {
        return factory;
    }
    public void setFactory(String factory) {
        this.factory = factory;
    }
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name + ", price=" + price
                + ", factory=" + factory + "]";
    }
    
}
一个简单的XML文件
<?xml version="1.0" encoding="utf-8"?>
<shopping>
    <product code="1">
        <name>薯片</name>
        <price>15</price>
        <factory>乐事</factory>
    </product>
    <product code="2">
        <name>可乐</name>
        <price>3</price>
        <factory>可口可乐</factory>
    </product>
</shopping>读取并解析现有XML或XML字符串的简单方法
/**
     * 读取并解析XML文件方法
     * @param xmlUrl 如果是读取本地工程文件使用此参数传入文件路径
     * @param xml  如果是传入xml字符串使用此参数
     * @return 解析后的XML字符串
     */
    public List<Product> readXML(String xmlUrl, String xml) {
        
        List<Product> list=new ArrayList<Product>();
        FileInputStream inXml = null;
        Document doc = null;
        
        // 判断为需解析的XML为本地文件或xml字符串
        try {
            
            if (xmlUrl !=null && !("".equals(xmlUrl))) {
                inXml = new FileInputStream(new File(xmlUrl));
                SAXReader saxReader = new SAXReader();
                // xml文档对应实体文档
                doc = saxReader.read(inXml);
            }
            if (xml !=null &&!("".equals(xml))) {
                // 将xml格式字符串转化为DOM对象
                doc = DocumentHelper.parseText(xml);
            }
            
            //获取shopping根元素下所有子元素
            List<Element> elementList=doc.selectNodes("//shopping/product");
            
            //以直接通过标签获取到XML的值
            for (Element em : elementList) {
                Product temp=new Product();
                //得到product标签的属性
                temp.setId(Long.parseLong(em.attributeValue("code")));
                //获取标签内文本值的方法
                temp.setName(em.elementText("name"));
                temp.setPrice(Double.parseDouble(em.elementText("price")));
                temp.setFactory(em.elementText("factory"));
                list.add(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                
                if(inXml != null){
                    inXml.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return list;
    }测试
public static void main(String[] args) {
        XMLUtils util = new XMLUtils();
        
        String src = "C:/shopping.xml";
        System.out.println("------读取XML文件并解析-------");
        System.out.println(util.readXML(src, null));
        
        String xml = "<?xml version='1.0' encoding='utf-8'?>"
                + "<shopping><product code='1'>"
                + "<name>老坛酸菜</name><"
                + "price>3.5</price>"
                + "<factory>统一</factory>"
                + "</product><product code='2'>"
                + "<name>加多宝</name>"
                + "<price>6</price>"
                + "<factory>加多宝</factory>"
                + "</product>"
                + "</shopping>";
        System.out.println("------读取XML格式字符串并解析-------");
        System.out.println(util.readXML(null, xml));
        
    }控制台输出结果
创建一个XML文件,个人感觉这个方法貌似并没有多大用,因为格式一般都是写好了,存成文件或者在数据库中的。
/**
     * 创建一个XML实体文件的方法
     * @param products 商品集合
     * @param fileName 文件名
     * @param src 文件保存地址
     * @return true 创建成功,false 创建失败
     */
    public boolean createXMLFile(List<Product> products,String fileName,String src){
        
        //默认创建成功
        boolean flag = true;
        try {
            //创建document对象
            Document document = DocumentHelper.createDocument();
            //创建根节点
            Element shoppingtElement = document.addElement("shopping");
            //加入一行注释
            shoppingtElement.addComment("这是一个商品的XML");
            //循环添加商品子节点
            for(int i = 0;i < products.size(); i++){
                //为shipping加入一个子节点
                Element product = shoppingtElement.addElement("product");
                //为product添加一个code属性
                product.addAttribute("code", String.valueOf(products.get(i).getId()));
                //为product添加子节点
                Element name = product.addElement("name");
                Element price = product.addElement("price");
                Element factory = product.addElement("factory");
                //给节点添加文本内容
                name.setText(products.get(i).getName());
                price.setText(String.valueOf(products.get(i).getPrice()));
                factory.setText(products.get(i).getFactory());
            }
            
            //生成XML文件
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            //判断保存目录是否存在
            File path = new File(src);
            if(!path.exists()){
                path.mkdirs();
                System.out.println("-----文件目录不存在,创建对应目录------------");
            }
            
            File xmlFile = new File(src+"\\"+fileName+".xml");
            XMLWriter writer = new XMLWriter(new FileOutputStream(xmlFile), format);
            writer.write(document);
            writer.flush();
            writer.close();
            
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
        
    }测试
运行结果,成功生成了一个test.xml
其实也可以直接用字符串拼接的方式实现新增一个XML,然后用Document document = DocumentHelper.parseText(xmlStr)方法把他转换为document对象输出成XML文件就可以了
修改一个现有的XML的方法,在实际的项目中,XML文件格式经常会以字符串的形式存在数据库中,这里我们以这种条件为前提,写个简单的方法,当传入一个XML字符串时,怎么实现修改
/**
     * 根据XML字符串创建一个实体XML文件
     * @param products 商品集合
     * @param fileName 文件名
     * @param src 文件保存地址
     * @param xmlStr 传入的xml格式文件
     * @return true 创建成功,false 创建失败
     */
    public boolean createXMLByStr(List<Product> products,String fileName,String src,String xmlStr){
        //默认转换成功
        boolean flag = true;
        try {
            //获取document对象
            Document document = DocumentHelper.parseText(xmlStr);
            //获取shopping根元素下所有子元素
            List<Element> elementList=document.selectNodes("//shopping/product");
            if(products.size() > 0){
                //模板中已经存在一条空白的标签,这里这么写是为了展现修改方法
                Element em = elementList.get(0);
                em.addAttribute("code", String.valueOf(products.get(0).getId()));
                em.element("name").setText(products.get(0).getName());
                em.element("price").setText(String.valueOf(products.get(0).getPrice()));
                em.element("factory").setText(products.get(0).getFactory());
            }
            //如果超过一条数据需要向XML追加节点
            if(products.size() > 1){
                //获取product节点上级父节点
                Element em = elementList.get(0).getParent();
                //循环添加商品子节点
                for(int i = 1;i < products.size(); i++){
                    //为shipping加入一个子节点
                    Element product = em.addElement("product");
                    //为product添加一个code属性
                    product.addAttribute("code", String.valueOf(products.get(i).getId()));
                    //为product添加子节点
                    Element name = product.addElement("name");
                    Element price = product.addElement("price");
                    Element factory = product.addElement("factory");
                    //给节点添加文本内容
                    name.setText(products.get(i).getName());
                    price.setText(String.valueOf(products.get(i).getPrice()));
                    factory.setText(products.get(i).getFactory());
                }
            }
            
            //生成XML文件
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            //判断保存目录是否存在
            File path = new File(src);
            if(!path.exists()){
                path.mkdirs();
                System.out.println("-----文件目录不存在,创建对应目录------------");
            }
            
            File xmlFile = new File(src+"\\"+fileName+".xml");
            XMLWriter writer = new XMLWriter(new FileOutputStream(xmlFile), format);
            writer.write(document);
            writer.flush();
            writer.close();
            
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        
        
        return flag;
        
    }测试
    public static void main(String[] args) {
        XMLUtils util = new XMLUtils();
        List<Product> list=new ArrayList<Product>();
        list.add(new Product(1L, "电脑", 6666, "联想"));
        list.add(new Product(2L, "手机", 7777, "苹果"));
        list.add(new Product(3L, "电视", 8888, "索尼"));
        
        String xml = "<?xml version='1.0' encoding='utf-8'?>"
                + "<shopping><product>"
                + "<name></name><"
                + "price></price>"
                + "<factory></factory>"
                + "</product>"
                + "</shopping>";
        System.out.println(util.createXMLByStr(list, "test", "c:\\test",xml));
        
    }运行结果
猜你喜欢
- 2024-10-17 Qt开发-DOM方式解析XML(qt开发工具)
- 2024-10-17 JAVA 操作笔记-XML(六)(xml在java中怎么用)
- 2024-10-17 作为一名程序猿,你不可不知的Java基础知识的三十个经典问答
- 2024-10-17 Android中XML文件解析,现在了解还不晚
- 2024-10-17 JSP 标准标签库(JSTL)(jsp标签库有哪些)
- 2024-10-17 Spring源码阅读:Spring XML解析机制
- 2024-10-17 XML文件(xml文件怎么打开)
- 2024-10-17 Python如何解析HTML和XML数据(python解析html xml最好的模块)
- 2024-10-17 深入解析Python中的XML处理:理论与实践的结合
- 2024-10-17 XML的解析方式(xml的解析方式有哪些)
欢迎 你 发表评论:
- 最近发表
- 标签列表
- 
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
 

本文暂时没有评论,来添加一个吧(●'◡'●)