java 中xml的使用

    XML 可扩展的标记语言
   XML 通用的数据格式标准
   在没有XML标准时代
     1 数据可以任意格式存储:二进制,文本格式
     2 数据的交换和分享出现麻烦
   XML 是一种通用的标准格式
     1 XML 数据格式标准
     2 可以用于文件的格式:XML 格式的文件称为XML 文件
     3 XML文件本身是文本文件,非常便于编辑和处理
        任何的文本编辑器都可以处理XML文件。

 

在解析xml之前要导入相应的jar包;

      XML 的语法结构:

     

<?xml version="1.0" encoding="UTF-8"?>
<!-- <?xml> 处理节点。处理指令, 建议在XML中第一行使用!处理节点之前不能用注释! -->
<!-- 注释节点 Comment Node  -->
<!-- 标记(标签)tag:<标记名> 称为标记 
     标记有3种: <标记名>开始标记, </标记名>结束标记, <标记名/>称为自结束标记
     XML 中标记必须配对出现 有开始标记一定有结束标记
     <标记名/>自结束标记是 无内容的<标记名></标记名>简写形式
     <标记名/> == <标记名></标记名> -->
<!-- 元素(Element): 开始标记+内容+结束标记 的整体称为元素 
    如: <book>老夫子</book> 称为元素 
  元素的内容:
     可以文本节点
     可以是其他元素
     可以是文本和元素的混合体    
     可以是元素的嵌套   -->
<!-- 
  文本节点: 元素中出现的文本称为文本节点
 -->
<!-- 
 属性:在元素的开始标记上可以定义元素的属性
   属性:属性名=“属性值” 
   属性值必须使用引用
   属性是无顺序的。 -->
<!-- 
  格式良好的XML(良构)
  1 XML文档只能有一个根元素。
  2 元素的嵌套要合理,不能交叉嵌套
   如下是错误的
    <book>
	<authors>
	</book>
	</authors>
  3 标记要配对
 -->
<!-- 
  因为XML的标记和内容定义没有约定,可以任意的扩展使用,称为可以扩展的标记语言!
 -->
<!-- 
  实体替换:XML的转移字符, 当在文本节点中使用特殊符号时候,需要使用实体符号替换
  
  & = &
  < = <
  > = >
  空格=  
 -->
<!-- CDATA 段:用于声明大段的文字,可以不进行实体替换 -->
<!-- XML 中的大小写是敏感的。 -->
<books>
	<book id="b01" lang="cn">老夫子
		<authors>	
			<author><佚名></author>
			<author>V&A</author>
			<author><![CDATA[
				<p>测试</p>
			]]></author>
		</authors>
	</book>
	<book></book>
</books>




下面是java操作xml:

 /**
    * Java 中 XML 文件的处理
    *  1 直接使用文本流处理XML文件。
    *    使用BufferedReader读取,使用PrintWriter写出。
    *    缺点:无法识别XML语法,不能按照元素进行处理
    *    优点:快!
    *  2 使用XML API 处理XML文档,W3C 提供了两种标准的XML API 
    *    SAX:
    *    优点:支持XML的语法,只支持读取操作,速度快, 占用内存小
    *    缺点:不能写XML,使用繁琐
    *    DOM:支持XML语法,速度没有SAX快,占用内存大,支持读写操作
    *    
    *    DOM4j:是第三方提供的API,不是W3C的标准,底层封装了 W3C DOM, 
    *       DOM4j API 简洁方便(比W3C DOM 方便!)  
    */
	//@Test
	public void testSAXAPI(){
		//利用SAX API 读取书籍的名字
		// 1 打开文件流 Class getResource;
		// 2 创建SAX 处理器(过滤器)
		// 3 创建SAX API 读取XML文件,并且利用处理器过滤XML文件
		// 4 在SAX处理期间,就得到了数据
		
		InputStream in = getClass().getResourceAsStream("books.xml");
		
		DefaultHandler handler = new DefaultHandler(){
			boolean foundName = false;
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				foundName = qName.equals("name");
				//读取book元素的id属性
				if (qName.equals("book")) {
					String id = attributes.getValue("id");
					System.out.println("Book ID:"+id); 
				}
			}
			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				if (foundName) {
					String bookName = new String(ch, start, length);
					System.out.println(bookName); 
				}
			}
			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				foundName = false;
				if(qName.equals("books")){
					throw new SAXException("结束了");
				}
			}
		};
		//使用 SAXParser 使用handler扫描读取XML文件,
		// SAXParser: 需要使用工厂模式创建SAXParser对象
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			
			parser.parse(in, handler);
			//parse 方法会从流in中读取XML文档,当遇到XML文档的结构时候,执行handler中适当
			// 事件处理方法 startElement endElement 等。
			// 异常: IOException 文档读取时候发送IO错误
			//      SAXException 文档不是格式良好,时候发送
			//        解析器抛出 SAX异常结束文件的读取
			
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * DOM4j  API 演示
	 */
	@Test
	public void testReadDoc(){
		try {
			InputStream in = TestCase.class.getResourceAsStream("books.xml");
			SAXReader reader = new SAXReader();
			//DOM4j 提供SAXReader,可将流读取为XML Doc
			//如果流读取失败,XML 不是良好格式,将出现异常
			Document doc = reader.read(in);
			in.close();
			//显示读取结果
			// Dom4j 的几乎所有API都有方法 asXML() 可以显示XML文档数据
			System.out.println(doc.asXML());
			//在doc中检索 全部的书名
			// dom4j 提供了树型结构的导航查询API方法
			// getRootElement() 获取文档的根元素
			// Element 代表内存中一个元素节点对象
			Element root = doc.getRootElement();
			//elements() 方法,可以获取一个元素的全部子元素节点
			// 重载的 elements(元素名) 获取一个元素的全都指定名称的子元素
			//List<Element> list = root.elements();
			List<Element> list = root.elements("book"); 
			for(Element e: list){
				//element(元素名) 获取一个元素的指定名称的子元素,如果重复,发回第一个子元素
				//Element n = e.element("name");
				//元素上一个方法 getText() 用于获取当前元素中文本内容
				//String name = n.getText();
				//getTextTrim() 方法可以获取文本,并且取出前后空白
				//name = n.getTextTrim();
				
				//dom4j 提供了更加便捷的API用于直接读取子元素中的文本
				String name = e.elementTextTrim("name");
				System.out.println(name); 
				
				//dom4j 可以读取元素的属性
				String id = e.attributeValue("id");
				System.out.println("book id:"+id);  
				//读取元素的全部属性
				//List<Attribute> attributes = e.attributes();
			}
			//修改内存中的DOC对象
			Element lastBook = list.get(list.size()-1);
			//setText() 方法可以修改元素节点的文本内容
			lastBook.element("price").setText("80.00"); 
			System.out.println(doc.asXML()); 
			//添加新元素等
			// 1 为根元素增加子元素book, addElement(元素名称) 返回新元素对象。
			Element newBook = root.addElement("book");
			// 2 增加元素
			newBook.addAttribute("id", "B03");
			newBook.addAttribute("lang", "CN");
			// 2 book增加子name元素,并且为name增加文本内容
			newBook.addElement("name").setText("红楼梦");
			newBook.addElement("price").setText("88.90");
			Element authors = newBook.addElement("authors");
			authors.addElement("author").setText("曹雪芹"); 
			//...
			
			System.out.println(doc.asXML()); 
			//写出Document 对象到文件, dom4j 提供的功能
			FileOutputStream out = new FileOutputStream("myBooks.xml");
			//设置输出格式: createPrettyPrint()创建漂亮的打印格式 
			OutputFormat format = OutputFormat.createPrettyPrint();
			XMLWriter writer = new XMLWriter(out, format);
			
			writer.write(doc);//XML Docuemnt 编码序列化到流
			writer.close();
			
 		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}


 

/**
	 * XML 是数据格式,不仅仅是文件
	 *  
	 *              读取                           写出
	 *  字符流           无语法支持,繁琐       无语法支持,快                  写出大规模的XML,要注意编码和语法结构
	 *  SAX      有语法支持,简便        不能写出                            适合大规模的XML读取,占用内存小
	 *  DOM4j    有语法支持,支持读取   有语法支持,写出           适合小规模XML读写,占用内存大
 	 *  W3C DOM   可以读                            可以写                             API非常繁琐,Java业界使用DOM4j替代之
 	 *  pull解析       有语法支持,简便             不能写                          适合大规模的XML读取,占用内存小
 	 *  
 	 *  pull解析: 特点是可以任意的暂停继续, 完全可以代替 SAX 
	 */
	//@Test
	public void testXmlPull() throws Exception{
		InputStream in = new BufferedInputStream(new FileInputStream("myBooks.xml"));
		//XmlPullParser 是接口,事例需要使用工厂创建
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		XmlPullParser pullParser = factory.newPullParser();
		
		//将被解析的流交给 pullParser, 不发送解析操作
		pullParser.setInput(new InputStreamReader(in, "utf-8"));
		
		//解析获取全部的书名
		
		boolean found = false;
		Scanner scanner = new Scanner(System.in);
		//COMMENT 遇到了注释
		//循环一直持续到 发生文件末尾事件为止
		main:
		for(int event = pullParser.getEventType();
				event !=END_DOCUMENT; 
				event = pullParser.nextToken()){
			//event = START_DOCUMENT COMMENT START_TAG TEXT START_TAG TEXT
			switch (event) {
			case COMMENT:
				System.out.println(pullParser.getText());//抓取注释的文本
				break ;
			case START_TAG:
				//从 XmlPullParser中拉取元素的开始标记名
				String name = pullParser.getName(); 
				if(name.equals("book")){
					String id = pullParser.getAttributeValue(0);
					System.out.println(id);
				}
				found = name.equals("name"); 
				break;
			case TEXT:
				if (found) {
					//拉取文本
					String text = pullParser.getText().trim();
					System.out.println(text);
				}
				break;
			case END_TAG:
				found = false;
			}
		}
		in.close();
				
		
	}
	
	/** 静态导入 */
	//@Test
	public void testStaticImport(){
		double x = sin(PI);
		System.out.println(x); 
	}
	
	/**
	 * w3school.com.cn 中文  
	 * w3schools.com   英文
	 * xpath 是XML 的一种查询语法
	 * myBooks.xml
	 * 抓取全部的 书名 节点的集合 
	 * String xpath = "/books/book/name"
	 * 在DOM对象上查找,就可以获取全部满足xpath的 Element对象
	 * dom4j 支持 xpath查找,在内存的Dom对象中查找 子节点
	 * 
	 * 1 xpath 的语法
	 * 2 dom4j API 支持xpath 查询
	 *    1 支持根部绝对路径查询
	 *      doc.selectNodes(xpath)   返回一个集合,包含全部满足条件的节点
	 *      doc.selectSingleNode(xpath) 返回第一个匹配的节点
	 *    2 支持相对路径查询,从某个元素节点开始执行查询
	 *      如 Element book 节点
	 *         book.selectNodes(xpath) 
	 *         book.selectSingleNode(xpath)
	 */
	//@Test
	public void testXpath() throws Exception{
		//打开Dom4j DOM 对象
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		//selectNodes 是在DOM 上执行xpath查询,将满足条件的元素 都作为返回值返回
		String xpath = "/books/book/name";
		List<Element> list = doc.selectNodes(xpath);
		//
		for (Element e : list) {
			System.out.println(e.asXML()); 
		}
	}
	public void testSelectSingleNode(String xpath) throws Exception{
		//打开Dom4j DOM 对象
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		Node node = doc.selectSingleNode(xpath);
		System.out.println(node.asXML());
	}
	public void testSelectNodes(String xpath) throws Exception{
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		List<Node> list = doc.selectNodes(xpath);
		for (Node node : list) {
			System.out.println(node.asXML()); 
		}
	}
	@Test
	public void testXPath() throws Exception{
		//testSelectSingleNode("/books"); 
		//testSelectNodes("/books/book");  
		//testSelectNodes("//.");  
		//XPATH 可以理解为 一层一层的过滤
		// "//" 代表所有节点, //author 所有节点中名字为author的节点。
		//testSelectNodes("//author");//查询结果节点是Element类型
		
		//查询所有节点中的 id属性节点
		//testSelectNodes("//@id");//查询结果节点是Attribute类型
		
		// DOM 节点的分类关系
		/* Node 节点
		 *  |-- Document 文档节点
		 *  |     |-- 只能包含一个根元素
		 *  |-- Element  元素节点 
		 *  |    |-- 可以包含其他节点和文本
		 *  |-- Comment 注释节点
		 *  |-- Text 文本节点
		 *  |-- Attribute 属性节点
		 */
		//testSelectNodes("/books/book[1]");
		//testSelectNodes("/books/book[last()]"); 
		//testSelectNodes("/books/book[1]/name");
		//testSelectNodes("/books/book[last()]/name"); 
		//testSelectNodes("/books/book[1]/authors/author[1]"); 	
		//testSelectNodes("/books/book[1]/authors/athor[1]"); 	
		//book有id属性被查询出来
		//testSelectNodes("/books/book[@id]"); 	
		 
		//testSelectNodes("/books/book[@id and price>85 and position()=1]"); 
		
		testSelectNodes("//*[.>85]"); 
		//  /*/*  与   /books/book  区别
	}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值