1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! High performance xml reader/writer. //! //! ## Description //! //! - `Reader`: a low level xml pull-reader where buffer allocation/clearing is left to user //! - `Writer`: a xml writer. Can be nested with readers if you want to transform xmls //! //! ## Examples //! //! ### Reader //! //! ```rust //! use quick_xml::reader::Reader; //! use quick_xml::events::Event; //! //! let xml = r#"<tag1 att1 = "test"> //! <tag2><!--Test comment-->Test</tag2> //! <tag2> //! Test 2 //! </tag2> //! </tag1>"#; //! //! let mut reader = Reader::from_str(xml); //! reader.trim_text(true); //! //! let mut count = 0; //! let mut txt = Vec::new(); //! let mut buf = Vec::new(); //! //! // The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s) //! loop { //! match reader.read_event(&mut buf) { //! // for triggering namespaced events, use this instead: //! // match reader.read_namespaced_event(&mut buf) { //! Ok(Event::Start(ref e)) => { //! // for namespaced: //! // Ok((ref namespace_value, Event::Start(ref e))) //! match e.name() { //! b"tag1" => println!("attributes values: {:?}", //! e.attributes().map(|a| a.unwrap().value) //! .collect::<Vec<_>>()), //! b"tag2" => count += 1, //! _ => (), //! } //! }, //! // unescape and decode the text event using the reader encoding //! Ok(Event::Text(e)) => txt.push(e.unescape_and_decode(&reader).unwrap()), //! Ok(Event::Eof) => break, // exits the loop when reaching end of file //! Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), //! _ => (), // There are several other `Event`s we do not consider here //! } //! //! // if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low //! buf.clear(); //! } //! ``` //! //! ### Writer //! //! ```rust //! use quick_xml::writer::Writer; //! use quick_xml::events::{Event, BytesEnd, BytesStart}; //! use quick_xml::reader::Reader; //! use std::io::Cursor; //! use std::iter; //! //! let xml = r#"<this_tag k1="v1" k2="v2"><child>text</child></this_tag>"#; //! let mut reader = Reader::from_str(xml); //! reader.trim_text(true); //! let mut writer = Writer::new(Cursor::new(Vec::new())); //! let mut buf = Vec::new(); //! loop { //! match reader.read_event(&mut buf) { //! Ok(Event::Start(ref e)) if e.name() == b"this_tag" => { //! //! // crates a new element ... alternatively we could reuse `e` by calling //! // `e.into_owned()` //! let mut elem = BytesStart::owned(b"my_elem".to_vec(), "my_elem".len()); //! //! // collect existing attributes //! elem.extend_attributes(e.attributes().map(|attr| attr.unwrap())); //! //! // copy existing attributes, adds a new my-key="some value" attribute //! elem.push_attribute(("my-key", "some value")); //! //! // writes the event to the writer //! assert!(writer.write_event(Event::Start(elem)).is_ok()); //! }, //! Ok(Event::End(ref e)) if e.name() == b"this_tag" => { //! assert!(writer.write_event(Event::End(BytesEnd::borrowed(b"my_elem"))).is_ok()); //! }, //! Ok(Event::Eof) => break, //! Ok(e) => assert!(writer.write_event(e).is_ok()), //! // or using the buffer //! // Ok(e) => assert!(writer.write(&buf).is_ok()), //! Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), //! } //! buf.clear(); //! } //! //! let result = writer.into_inner().into_inner(); //! let expected = r#"<my_elem k1="v1" k2="v2" my-key="some value"><child>text</child></my_elem>"#; //! assert_eq!(result, expected.as_bytes()); //! ``` #![deny(missing_docs)] #![recursion_limit = "1024"] extern crate encoding_rs; #[macro_use] extern crate failure; extern crate memchr; pub mod errors; pub mod reader; pub mod writer; pub mod events; mod escape; // reexports pub use writer::Writer;