#![allow(dead_code)] use quick_xml::events::BytesText; use quick_xml::{events::Event, name::ResolveResult}; use raxb::de::{XmlDeserialize, XmlDeserializeError}; use raxb::ser::{XmlSerialize, XmlSerializeError}; use raxb::ty::S; #[derive(Debug)] pub struct Envelope { pub header: bool, pub body: T, } impl XmlDeserialize for Envelope where T: XmlDeserialize + std::fmt::Debug, { fn root() -> Option { Some(b"Envelope") } fn target_ns() -> Option { Some(b"http://schemas.xmlsoap.org/soap/envelope/") } fn xml_deserialize( reader: &mut quick_xml::NsReader, target_ns: raxb::ty::XmlTag, tag: raxb::ty::XmlTargetNs, _attributes: quick_xml::events::attributes::Attributes, _is_empty: bool, ) -> raxb::de::XmlDeserializeResult where Self: Sized, R: std::io::prelude::BufRead, { let target_ns = Self::target_ns().unwrap_or(target_ns); let mut buf = Vec::::new(); let mut body = Option::::None; loop { match reader.read_resolved_event_into(&mut buf)? { (ResolveResult::Bound(ns), Event::Start(ev)) if ns.as_ref() == target_ns => { match ev.local_name().as_ref() { b"Body" => { body = Some(T::xml_deserialize( reader, target_ns, b"Body", ev.attributes(), false, )?); } _ => { let mut buffer: Vec = Vec::::new(); reader.read_to_end_into(ev.name(), &mut buffer)?; } } } (ResolveResult::Bound(ns), Event::End(e)) if ns.as_ref() == target_ns && e.local_name().as_ref() == tag => { break; } (_, Event::Eof) => { break; } _ => {} } } Ok(Self { header: true, body: body.ok_or(XmlDeserializeError::MissingElement(S(b"Body")))?, }) } } impl XmlSerialize for Envelope where T: XmlSerialize, { fn root() -> Option { Some(b"SOAP-ENV:Envelope") } fn xml_serialize( &self, tag: &str, writer: &mut quick_xml::Writer, ) -> raxb::ser::XmlSerializeResult<()> { let mut el_writer = writer.create_element(tag); el_writer = el_writer.with_attribute(( "xmlns:SOAP-ENV", "https://schemas.xmlsoap.org/soap/envelope/", )); el_writer.write_inner_content::<_, XmlSerializeError>(|writer| { writer.create_element("SOAP-ENV:Header").write_empty()?; self.body.xml_serialize("SOAP-ENV:Body", writer)?; Ok(()) })?; Ok(()) } } #[derive(Debug)] pub struct Header { pub content: String, } impl XmlDeserialize for Header { fn root() -> Option { Some(b"Example") } fn target_ns() -> Option { Some(b"https://my.example.org/") } fn xml_deserialize( reader: &mut quick_xml::NsReader, target_ns: raxb::ty::XmlTag, tag: raxb::ty::XmlTargetNs, _attributes: quick_xml::events::attributes::Attributes, _is_empty: bool, ) -> raxb::de::XmlDeserializeResult where Self: Sized, R: std::io::prelude::BufRead, { let target_ns = ::target_ns().unwrap_or(target_ns); let mut buf = Vec::::new(); let mut content: Option = Option::::None; loop { match reader.read_resolved_event_into(&mut buf)? { (_, Event::Text(ev)) => content = Some(ev.unescape()?.to_string()), (ResolveResult::Bound(ns), Event::End(e)) if e.local_name().as_ref() == tag && ns.as_ref() == target_ns => { break; } (_, Event::Eof) => { break; } _ => {} } } Ok(Self { content: content.ok_or(XmlDeserializeError::EmptyNode)?, }) } } impl XmlSerialize for Header { fn xml_serialize( &self, tag: &str, writer: &mut quick_xml::Writer, ) -> raxb::ser::XmlSerializeResult<()> { writer .create_element(tag) .with_attribute(("xmlns:example", "https://my.example.org/")) .write_text_content(BytesText::from_escaped("BASE_64_ENCODED_XML"))?; Ok(()) } } #[derive(Debug)] pub struct Example { pub header: Header, } impl XmlDeserialize for Example { fn root() -> Option { Some(b"Example") } fn target_ns() -> Option { Some(b"https://my.example.org/") } fn xml_deserialize( reader: &mut quick_xml::NsReader, target_ns: raxb::ty::XmlTargetNs, tag: raxb::ty::XmlTag, _attributes: quick_xml::events::attributes::Attributes, _is_empty: bool, ) -> raxb::de::XmlDeserializeResult where Self: Sized, R: std::io::prelude::BufRead, { let target_ns = ::target_ns().unwrap_or(target_ns); let mut buf = Vec::::new(); let mut header = Option::
::None; loop { match reader.read_resolved_event_into(&mut buf)? { (ResolveResult::Bound(ns), Event::Start(ev)) if ns.as_ref() == target_ns => { match ev.local_name().as_ref() { b"header" => { header = Some(Header::xml_deserialize( reader, target_ns, b"header", ev.attributes(), false, )?); } _ => { let mut buffer: Vec = Vec::::new(); reader.read_to_end_into(ev.name(), &mut buffer)?; } } } (ResolveResult::Bound(ns), Event::End(e)) if e.local_name().as_ref() == tag && ns.as_ref() == target_ns => { break; } (_, Event::Eof) => { break; } _ => {} } } Ok(Self { header: header.ok_or(XmlDeserializeError::MissingElement(S(b"header")))?, }) } } impl XmlSerialize for Example { fn xml_serialize( &self, tag: &str, writer: &mut quick_xml::Writer, ) -> raxb::ser::XmlSerializeResult<()> { writer .create_element(tag) .write_inner_content::<_, XmlSerializeError>(|writer| { self.header.xml_serialize("example:header", writer)?; Ok(()) })?; Ok(()) } } #[test] fn test_serialize_ns_manual() -> anyhow::Result<()> { let xml = raxb::ser::to_string(&Envelope:: { header: true, body: Example { header: Header { content: "BASE_64_ENCODED_XML".to_string(), }, }, })?; assert_eq!( xml, r#"BASE_64_ENCODED_XML"# ); Ok(()) } #[test] fn test_deserialize_ns_manual() -> anyhow::Result<()> { let xml = r#" BASE_64_ENCODED_XML "#; let envelope: Envelope = raxb::de::from_str(xml)?; eprintln!("{envelope:#?}"); Ok(()) }