汇总:xml的构造与解析 http://www.cnblogs.com/gnivor/p/4624058.html
参考资料:http://www.iteye.com/topic/763895
利用SAX存储XML(一般不这么用)
import java.io.FileNotFoundException; import java.io.FileOutputStream; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; public class MySax { public static void main(String[] args) throws FileNotFoundException, TransformerConfigurationException, SAXException{ MySax mysax = new MySax(); mysax.generate(); } //生成xml文档的函数 public void generate() throws FileNotFoundException, TransformerConfigurationException, SAXException{ Result resultXml = new StreamResult(new FileOutputStream("c:\person.xml")); //输出到person.xml SAXTransformerFactory sff = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); TransformerHandler th = sff.newTransformerHandler(); th.setResult(resultXml); Transformer transformer = th.getTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //编码格式是UTF-8 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //换行 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");// 是否忽略xml声明 AttributesImpl attr = new AttributesImpl(); th.startDocument(); //开始xml文档 th.startElement("", "", "person", attr); //定义person节点 th.startElement("", "", "name", attr); //定义name节点 th.characters("张三".toCharArray(), 0, "张三".length()); th.endElement("", "", "name"); //结束name节点 th.startElement("", "", "age", attr); //定义age节点 th.characters("29".toCharArray(), 0, "29".length()); th.endElement("", "", "age"); //结束age节点 th.startElement("", "", "gender", attr); //定义gender节点 th.characters("男".toCharArray(), 0, "男".length()); th.endElement("", "", "gender"); //结束gender节点 th.endElement("", "", "person"); //结束person节点 th.endDocument(); //结束xml文档 } }
利用SAX对XML进行解析
要解析的文件
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="12"> <name>thinking in java</name> <price>85.5</price> </book> <book id="15"> <name>Spring in Action</name> <price>39.0</price> </book> </books>
解析方法
xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析。
当读入<?xml.....>时,会调用startDocument()方法,
当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法。
注意:上面方法第二个参数就是节点的名称.由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用。第4个参数是这个节点的属性。
我们不需要<books>这个节点,所以从<book>这个节点开始,也就是图中1的位置。
当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到,
然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。具体见代码。
Book
class Book { private int id; private String name; private float price; public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPrice(float price) { this.price = price; } @Override public String toString(){ return "id:"+ this.id+", 书名:"+this.name+", 价格:"+this.price; } }
SaxParseService
class SaxParseService extends DefaultHandler{ private List<Book> books = null; private Book book = null; private String preTag = null;//作用是记录解析时的上一个节点名称 public List<Book> getBooks(InputStream xmlStream) throws Exception{ SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); SaxParseService handler = new SaxParseService(); parser.parse(xmlStream, handler); //对文件流进行解析 return handler.books; //返回结果 } //第1个分析点事件方法。在该方法中创建了用于保存 转换结果的List<Book>对象 @Override public void startDocument() throws SAXException { books = new ArrayList<Book>(); } //第2个分析点事件方法。SAX引擎分析到每一个<book>元素时,在该方法中都会创建一个Book对象 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if("book".equals(qName)){ book = new Book(); book.setId(Integer.parseInt(attributes.getValue(0))); } preTag = qName;//将正在解析的节点名称赋给preTag } //第3个分析点事件方法。当SAX引擎每分析完一个XML元素之后,会将当前book加入到Books列表之中 @Override public void endElement(String uri, String localName, String qName) throws SAXException { if("book".equals(qName)){ books.add(book); book = null; } preTag = null; /* 当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法 * ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图 * 中标记4的位置时,会执行characters(char[] ch, int start, int length)这个方法, * 而characters(....)方法判断preTag!=null,会执行if判断的代码, * 这样就会把空值赋值给book,这不是我们想要的。 * */ } //第4个分析点事件方法。分析每一个book元素,并将book元素的属性保存在Book对象之中 @Override public void characters(char[] ch, int start, int length) throws SAXException { if(preTag!=null){ String content = new String(ch,start,length); if("name".equals(preTag)){ book.setName(content); }else if("price".equals(preTag)){ book.setPrice(Float.parseFloat(content)); } } } }
测试类
public class BookSax { public static void main(String[] args) throws Throwable{ BookSax booksax = new BookSax(); booksax.testSAX(); } public void testSAX() throws Throwable{ SaxParseService sax = new SaxParseService(); File file = new File("F:\测试TXT\book.xml"); FileInputStream input = new FileInputStream(file); List<Book> books = sax.getBooks(input); for(Book book : books){ System.out.println(book.toString()); } } }
运行结果:
id:12, 书名:thinking in java, 价格:85.5
id:15, 书名:Spring in Action, 价格:39.0