use crate::{XMLVersion, sax::Attributes};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) enum XMLEventType {
#[default]
StartDocument,
EndDocument,
StartElement,
EndElement,
StartEmptyTag,
EndEmptyTag,
Declaration,
DocumentType,
Characters,
CDATASection,
Space,
Comment,
ProcessingInstruction,
StartEntity,
EndEntity,
FatalError,
Finished,
}
pub enum XMLEvent<'a> {
StartDocument,
EndDocument,
StartElement(StartElement<'a>),
EndElement(EndElement<'a>),
Declaration(Declaration<'a>),
DocumentType,
Characters(&'a str),
CDATASection(&'a str),
Space(&'a str),
Comment(&'a str),
ProcessingInstruction(ProcessingInstruction<'a>),
StartEntity(&'a str),
EndEntity,
FatalError,
Finished,
}
impl std::fmt::Debug for XMLEvent<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
XMLEvent::StartDocument => write!(f, "startDocument()"),
XMLEvent::EndDocument => write!(f, "endDocument()"),
XMLEvent::StartElement(start) => {
write!(
f,
"startElement({}, {}, {}, {}",
start.namespace_name().unwrap_or("None"),
start.prefix().unwrap_or("None"),
start.local_name().unwrap_or("None"),
start.name()
)?;
for att in start.attributes() {
write!(f, ", ")?;
if let Some(local_name) = att.local_name.as_deref() {
if let Some(uri) = att.namespace_name.as_deref() {
write!(f, "{{{uri}}}")?;
}
write!(f, "{local_name}='{}'", att.value)?;
} else {
write!(f, "{}='{}'", att.qname, att.value)?;
}
}
write!(f, ")")
}
XMLEvent::EndElement(end) => {
write!(
f,
"endElement({}, {}, {}, {})",
end.namespace_name().unwrap_or("None"),
end.prefix().unwrap_or("None"),
end.local_name().unwrap_or("None"),
end.name()
)
}
XMLEvent::Declaration(declaration) => {
write!(
f,
"declaration({}, {}, ",
declaration.version(),
declaration.encoding().unwrap_or("None")
)?;
if let Some(standalone) = declaration.standalone() {
if standalone {
write!(f, "yes)")
} else {
write!(f, "no)")
}
} else {
write!(f, "None)")
}
}
XMLEvent::DocumentType => write!(f, "documentType()"),
XMLEvent::Characters(characters) => {
write!(f, "characters({characters})")
}
XMLEvent::CDATASection(cdata) => write!(f, "cdataSection({cdata})"),
XMLEvent::Space(space) => write!(f, "space({space})"),
XMLEvent::Comment(comment) => write!(f, "comment({comment})"),
XMLEvent::ProcessingInstruction(pi) => write!(
f,
"processingInstruction({}, '{}')",
pi.target(),
pi.data().unwrap_or("None")
),
XMLEvent::StartEntity(entity) => write!(f, "startEntity({entity})"),
XMLEvent::EndEntity => write!(f, "endEntity()"),
XMLEvent::FatalError => write!(f, "fatalError()"),
XMLEvent::Finished => write!(f, "finished()"),
}
}
}
pub struct StartElement<'a> {
pub(super) namespace_name: Option<&'a str>,
pub(super) local_name: Option<&'a str>,
pub(super) qname: &'a str,
pub(super) atts: &'a Attributes,
}
impl StartElement<'_> {
pub fn name(&self) -> &str {
self.qname
}
pub fn local_name(&self) -> Option<&str> {
self.local_name
}
pub fn prefix(&self) -> Option<&str> {
let local_name = self.local_name?;
let prefix_len = self.qname.len() - local_name.len();
(prefix_len > 0).then(|| &self.qname[..prefix_len - 1])
}
pub fn namespace_name(&self) -> Option<&str> {
self.namespace_name
}
pub fn attributes(&self) -> &Attributes {
self.atts
}
}
pub struct EndElement<'a> {
pub(super) namespace_name: Option<&'a str>,
pub(super) local_name: Option<&'a str>,
pub(super) qname: &'a str,
}
impl EndElement<'_> {
pub fn name(&self) -> &str {
self.qname
}
pub fn local_name(&self) -> Option<&str> {
self.local_name
}
pub fn prefix(&self) -> Option<&str> {
let local_name = self.local_name?;
let prefix_len = self.qname.len() - local_name.len();
(prefix_len > 0).then(|| &self.qname[..prefix_len - 1])
}
pub fn namespace_name(&self) -> Option<&str> {
self.namespace_name
}
}
pub struct Declaration<'a> {
pub(super) version: XMLVersion,
pub(super) encoding: Option<&'a str>,
pub(super) standalone: Option<bool>,
}
impl Declaration<'_> {
pub fn version(&self) -> XMLVersion {
self.version
}
pub fn encoding(&self) -> Option<&str> {
self.encoding
}
pub fn is_standalone(&self) -> bool {
self.standalone == Some(true)
}
pub fn standalone(&self) -> Option<bool> {
self.standalone
}
}
pub struct ProcessingInstruction<'a> {
pub(super) target: &'a str,
pub(super) data: Option<&'a str>,
}
impl ProcessingInstruction<'_> {
pub fn target(&self) -> &str {
self.target
}
pub fn data(&self) -> Option<&str> {
self.data
}
}