use oxml::stream::{Event, Reader};
use oxml::{Limits, parse};
const DOC: &str = r#"<?xml version="1.0"?>
<catalogue xmlns:m="urn:example:meta">
<item id="a1"><name>Tea</name><m:added>2026-01-04</m:added></item>
<item id="a2"><name>Coffee</name><m:added>2026-02-11</m:added></item>
<item id="a3"><name>Cocoa</name><m:added>2026-03-27</m:added></item>
</catalogue>
"#;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut reader = Reader::new(DOC)?;
let mut depth = 0usize;
let mut items = 0usize;
while let Some(event) = reader.next_event()? {
match event {
Event::StartElement { name, attributes } => {
let attrs: Vec<String> = attributes
.iter()
.map(|(n, v)| format!(" {}={v:?}", n.local))
.collect();
println!(
"{:indent$}<{}>{}",
"",
name.local,
attrs.concat(),
indent = depth * 2
);
if name.local == "item" {
items += 1;
}
depth += 1;
}
Event::EndElement { .. } => depth = depth.saturating_sub(1),
Event::Text(text) if !text.trim().is_empty() => {
println!("{:indent$}{}", "", text.trim(), indent = depth * 2);
}
_ => {}
}
}
println!("\n{items} items");
let mut reader = Reader::new(DOC)?;
while let Some(event) = reader.next_event()? {
if let Event::StartElement { name, .. } = event {
if let Some(uri) = name.namespace {
println!("{} is in {uri:?}", name.local);
break;
}
}
}
let mut limits = Limits::default();
limits.max_depth = 2;
let mut reader = Reader::with_limits(DOC, limits)?;
let refused = loop {
match reader.next_event() {
Ok(Some(_)) => {}
Ok(None) => break None,
Err(error) => break Some(error),
}
};
println!(
"with max_depth(2): {}",
match &refused {
Some(error) => error.to_string(),
None => "read to the end".to_owned(),
}
);
let mut reader =
Reader::from_reader(std::io::Cursor::new(DOC.as_bytes().to_vec()))?;
let mut from_source = 0usize;
while let Some(event) = reader.next_event()? {
if matches!(event, Event::StartElement { .. }) {
from_source += 1;
}
}
println!("\nfrom a byte source: {from_source} elements");
let mut reader = Reader::from_reader_with(
std::io::Cursor::new(DOC.as_bytes().to_vec()),
Limits::default(),
)?;
let mut counted = 0usize;
while reader.next_event()?.is_some() {
counted += 1;
}
println!("from a byte source with limits: {counted} events");
let malformed = "<a><b></a>";
println!(
"\n{malformed:?}\n parse: {}\n stream: {}",
parse(malformed).unwrap_err(),
Reader::new(malformed)
.and_then(|mut r| {
while r.next_event()?.is_some() {}
Ok(())
})
.unwrap_err()
);
Ok(())
}