✨ feat(mq-lang): replace XML parser with native quick-xml builtin#1464
✨ feat(mq-lang): replace XML parser with native quick-xml builtin#1464
Conversation
Replace the mq-lang XML parser implementation with a native `_xml_parse` builtin backed by the `quick-xml` crate, consistent with the JSON and toon-format native builtin migrations.
There was a problem hiding this comment.
Pull request overview
This PR introduces a native Rust-backed XML parser in mq-lang using quick-xml, replacing the previous mq-script implementation and wiring it into the existing xml::xml_parse module API.
Changes:
- Added
_xml_parsebuiltin implemented viaquick-xmlthat returns the existing{tag, attributes, children, text}structure. - Updated
modules/xml.mqto delegate XML parsing to the new builtin. - Added
quick-xmldependency, registered builtin dispatch/docs, and added Rust unit tests for the new builtin.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| crates/mq-lang/src/eval/builtin.rs | Adds _xml_parse builtin + dispatch/doc entries + unit tests. |
| crates/mq-lang/modules/xml.mq | Replaces mq-script XML parsing implementation with a thin wrapper calling _xml_parse. |
| crates/mq-lang/Cargo.toml | Adds quick-xml dependency needed by the new builtin. |
| Cargo.lock | Records the new quick-xml dependency resolution. |
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR adds a native XML parsing builtin to mq-lang using quick-xml, replacing the previous pure-mq implementation in the xml module.
Changes:
- Introduces a new internal builtin function
_xml_parseimplemented in Rust viaquick-xml. - Updates
xml::xml_parseto delegate to_xml_parseinstead of the old mq-based XML parser. - Adds
quick-xmlas a dependency and includes unit tests + builtin documentation for_xml_parse.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| crates/mq-lang/src/eval/builtin.rs | Adds _xml_parse builtin implementation, dispatch wiring, docs entry, and Rust unit tests. |
| crates/mq-lang/modules/xml.mq | Replaces mq-based XML parsing with a call to the new _xml_parse builtin. |
| crates/mq-lang/Cargo.toml | Adds quick-xml dependency for the new builtin. |
| Cargo.lock | Locks quick-xml and its transitive dependencies. |
| return Err(Error::Runtime(format!( | ||
| "XML parse error at position {}: {}", | ||
| reader.buffer_position(), | ||
| e | ||
| ))); | ||
| } | ||
| _ => (), | ||
| } | ||
| buf.clear(); | ||
| } | ||
|
|
||
| Ok(root.unwrap_or(RuntimeValue::NONE)) | ||
| } | ||
| [a] => Err(Error::InvalidTypes(ident.to_string(), vec![std::mem::take(a)])), | ||
| _ => unreachable!(), |
| let mut dict = BTreeMap::new(); | ||
| dict.insert(Ident::new("tag"), RuntimeValue::String(tag)); | ||
| dict.insert(Ident::new("attributes"), RuntimeValue::Dict(attrs)); | ||
| dict.insert(Ident::new("children"), RuntimeValue::Array(children)); | ||
| dict.insert( | ||
| Ident::new("text"), | ||
| text.map(RuntimeValue::String).unwrap_or(RuntimeValue::NONE), |
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR introduces a native Rust XML parsing builtin in mq-lang using quick-xml, and rewires the xml module to use it instead of the previous pure-mq XML parser implementation.
Changes:
- Add
_xml_parsebuiltin implemented withquick-xmland register it in the builtin lookup + internal docs. - Simplify
modules/xml.mqsoxml_parse(...)delegates to the new_xml_parse(...). - Add
quick-xmlas a dependency (and updateCargo.lockaccordingly), plus unit tests for basic XML parsing scenarios.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| crates/mq-lang/src/eval/builtin.rs | Implements and registers _xml_parse, documents it, and adds tests. |
| crates/mq-lang/modules/xml.mq | Replaces the old mq-based XML parser with a thin wrapper around _xml_parse. |
| crates/mq-lang/Cargo.toml | Adds quick-xml dependency required by the new builtin. |
| Cargo.lock | Locks quick-xml and its transitive dependencies. |
| let key = String::from_utf8_lossy(attr.key.as_ref()).to_string(); | ||
| let value = attr | ||
| .decode_and_unescape_value(reader.decoder()) | ||
| .map_err(|e| Error::Runtime(format!("XML attribute value error: {}", e)))? | ||
| .to_string(); | ||
| attrs.insert(Ident::new(&key), RuntimeValue::String(value)); |
| let mut dict = BTreeMap::new(); | ||
| dict.insert(Ident::new("tag"), RuntimeValue::String(tag)); | ||
| dict.insert(Ident::new("attributes"), RuntimeValue::Dict(attrs)); | ||
| dict.insert(Ident::new("children"), RuntimeValue::Array(children)); | ||
| dict.insert( | ||
| Ident::new("text"), | ||
| text.map(RuntimeValue::String).unwrap_or(RuntimeValue::NONE), | ||
| ); |
| Ok(quick_xml::events::Event::Text(e)) => { | ||
| if let Some(parent) = stack.last_mut() { | ||
| let text = reader | ||
| .decoder() | ||
| .decode(e.as_ref()) | ||
| .map_err(|e| Error::Runtime(format!("XML text error: {}", e)))? | ||
| .to_string(); | ||
|
|
||
| if !text.is_empty() { | ||
| match &mut parent.3 { | ||
| Some(t) => t.push_str(&text), | ||
| None => parent.3 = Some(text), | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Ok(quick_xml::events::Event::CData(e)) => { | ||
| if let Some(parent) = stack.last_mut() { | ||
| let text = reader | ||
| .decoder() | ||
| .decode(e.as_ref()) | ||
| .map_err(|e| Error::Runtime(format!("XML CDATA error: {}", e)))? | ||
| .to_string(); | ||
| match &mut parent.3 { | ||
| Some(t) => t.push_str(&text), | ||
| None => parent.3 = Some(text), | ||
| } | ||
| } | ||
| } | ||
| Ok(quick_xml::events::Event::Eof) => break, |
| thiserror = {workspace = true} | ||
| url = {workspace = true} | ||
| toon-format = { version = "0.4", default-features = false } | ||
| quick-xml = "0.39.2" |
No description provided.