3

I send an http get request to a server and receive a response:

let resp = reqwest::blocking::get(req)?.text()?;

resp holds a String like this:

<?xml version=\"1.0\" encoding=\"UTF-8\">\n<Document xmlns=...
<datetime>202207102300</datetime>\n\t\t\t\t\t\t<value>320.08</value>\n\t\t\t\t\t<datetime>202207110000</datetime>\n\t\t\t\t\t\t<value>278.00</value>
...</Document>

What is the best way to get this text parsed into a vector containing tuple elements, as follows:

let mut tuple_items: (chrono::DateTime, f32)
Bowers
  • 836
  • 8
  • 20
  • 1
    Is the response a list of XML tags or is there a parent/root tag that you haven't shown? – Peter Hall Jul 31 '22 at 19:51
  • @PeterHall thanks for this good question. Updated my question. – Bowers Jul 31 '22 at 20:04
  • 3
    Ddi you try any of the XML crates? quickxml, serde-xml-rs etc.. – Peter Hall Jul 31 '22 at 20:11
  • @PeterHall No so far I have only tried to parse the string, which resulted in an inelegant solution, which is why I asked the question. But thanks, I will test tomorrow. – Bowers Jul 31 '22 at 20:18
  • [Parsing XML/HTML is not easy](https://stackoverflow.com/a/1732454/3398839)... I strongly recommend using a library to parse it. In a case as simple as this one, you *might* get away with better simplicity/performance by just parsing it manually, but I would caution against that! – Coder-256 Aug 01 '22 at 01:30

1 Answers1

1

This is my code that I created with the quickxml crate:

use chrono::NaiveDateTime;
use quick_xml::events::Event;
use quick_xml::Reader;

pub struct DatetimeValue {
    pub dt: NaiveDateTime,
    pub val: f32,
}    

pub fn parse_xml_string(&self, xml_string: String) -> Vec<DatetimeValue> {
    let mut response_vector: Vec<DatetimeValue> = vec![];
    let mut reader = Reader::from_str(&xml_string[..]);
    reader.trim_text(true);
    let mut val_flag = false;
    let mut dt_flag = false;
    let mut buf = Vec::new();
    let mut count = 0;
    let mut actual_dt: NaiveDateTime;
    loop {
        match reader.read_event(&mut buf) {
            Ok(Event::Start(ref e)) => {
                if let b"value" = e.name() { val_flag = true }
                else if let b"datetime" = e.name() { dt_flag = true }
            }
            Ok(Event::Text(e)) => {
                if dt_flag {
                    actual_dt = NaiveDateTime::parse_from_str(e
                            .unescape_and_decode(&reader)
                            .unwrap(), "%Y%m%d%H%M").unwrap();
                    dt_flag = false;
                }
                else if val_flag {
                    response_vector.push(DatetimeValue {
                        dt: actual_dt,
                        val: e
                            .unescape_and_decode(&reader)
                            .unwrap()
                            .parse::<f32>()
                            .unwrap(),
                    });
                    val_flag = false;
                }
            }
            Ok(Event::Eof) => break,
            Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
            _ => (),
        }
        buf.clear();
    }
    response_vector
}
Bowers
  • 836
  • 8
  • 20