Add a function to get a named xml element
This commit is contained in:
@@ -184,6 +184,7 @@ For everything else please have a look at the [detailed list][1].
|
||||
- [utf8_decode](https://sn0int.readthedocs.io/en/latest/reference.html#utf8-decode)
|
||||
- [x509_parse_pem](https://sn0int.readthedocs.io/en/latest/reference.html#x509-parse-pem)
|
||||
- [xml_decode](https://sn0int.readthedocs.io/en/latest/reference.html#xml-decode)
|
||||
- [xml_named](https://sn0int.readthedocs.io/en/latest/reference.html#xml-named)
|
||||
|
||||
## Rationale
|
||||
|
||||
|
||||
@@ -914,3 +914,19 @@ Decode a lua value from an xml document.
|
||||
|
||||
print(foo['attrs']['fizz'])
|
||||
print(foo['text'])
|
||||
|
||||
xml_named
|
||||
---------
|
||||
|
||||
Get a named child element from a parent element.
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
x = xml_decode('<body><foo fizz="buzz">bar</foo></body>')
|
||||
if last_err() then return end
|
||||
|
||||
body = x['children'][1]
|
||||
foo = xml_named(body, 'foo')
|
||||
if foo ~= nil then
|
||||
print(foo)
|
||||
end
|
||||
|
||||
@@ -395,6 +395,7 @@ fn ctx<'a>(env: Environment, logger: Arc<Mutex<Box<Reporter>>>) -> (hlua::Lua<'a
|
||||
runtime::utf8_decode(&mut lua, state.clone());
|
||||
runtime::x509_parse_pem(&mut lua, state.clone());
|
||||
runtime::xml_decode(&mut lua, state.clone());
|
||||
runtime::xml_named(&mut lua, state.clone());
|
||||
|
||||
debug!("Created lua context");
|
||||
|
||||
|
||||
@@ -12,6 +12,70 @@ pub fn xml_decode(lua: &mut hlua::Lua, state: Arc<State>) {
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn key_is(key: &AnyLuaValue, expected: &str) -> bool {
|
||||
match key {
|
||||
AnyLuaValue::LuaString(key) => key.as_str() == expected,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_children(xml: AnyLuaValue) -> Option<AnyLuaValue> {
|
||||
match xml {
|
||||
AnyLuaValue::LuaArray(arr) => {
|
||||
for (key, value) in arr {
|
||||
if key_is(&key, "children") {
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn match_element_name(xml: &AnyLuaValue, name: &str) -> bool {
|
||||
match xml {
|
||||
AnyLuaValue::LuaArray(arr) => {
|
||||
for (key, value) in arr {
|
||||
if key_is(key, "name") {
|
||||
match value {
|
||||
AnyLuaValue::LuaString(key) => {
|
||||
return key.as_str() == name
|
||||
},
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn xml_named(lua: &mut hlua::Lua, _state: Arc<State>) {
|
||||
lua.set("xml_named", hlua::function2(move |xml: AnyLuaValue, name: String| -> AnyLuaValue {
|
||||
if let Some(value) = get_children(xml) {
|
||||
match value {
|
||||
AnyLuaValue::LuaArray(arr) => {
|
||||
for (_, value) in arr {
|
||||
if match_element_name(&value, &name) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
AnyLuaValue::LuaNil
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::engine::ctx::Script;
|
||||
@@ -29,7 +93,7 @@ mod tests {
|
||||
return 'wrong body tag name'
|
||||
end
|
||||
|
||||
foo = body['named']['foo']
|
||||
foo = xml_named(body, 'foo')
|
||||
if foo['name'] ~= 'foo' then
|
||||
return 'foo has wrong tag name'
|
||||
end
|
||||
|
||||
34
src/xml.rs
34
src/xml.rs
@@ -28,7 +28,6 @@ pub struct XmlElement {
|
||||
pub attrs: HashMap<String, String>,
|
||||
pub text: Option<String>,
|
||||
pub children: Vec<XmlElement>,
|
||||
pub named: HashMap<String, XmlElement>,
|
||||
}
|
||||
|
||||
impl XmlElement {
|
||||
@@ -43,7 +42,6 @@ impl XmlElement {
|
||||
attrs,
|
||||
text: None,
|
||||
children: Vec::new(),
|
||||
named: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,12 +98,11 @@ fn decode_raw(x: &str) -> Result<XmlDocument> {
|
||||
|
||||
let name = name.local_name;
|
||||
if child.name != name {
|
||||
bail!("todo")
|
||||
bail!("end element name doesn't match start element name")
|
||||
}
|
||||
|
||||
if let Some(tail) = stack.last_mut() {
|
||||
tail.children.push(child.clone());
|
||||
tail.named.insert(name, child);
|
||||
tail.children.push(child);
|
||||
} else {
|
||||
doc.children.push(child);
|
||||
}
|
||||
@@ -118,7 +115,7 @@ fn decode_raw(x: &str) -> Result<XmlDocument> {
|
||||
|
||||
// TODO: consider ignoring this?
|
||||
if !stack.is_empty() {
|
||||
bail!("todo")
|
||||
bail!("end of document but still open elements remaining")
|
||||
}
|
||||
|
||||
Ok(doc)
|
||||
@@ -144,7 +141,6 @@ mod tests {
|
||||
attrs: HashMap::new(),
|
||||
text: None,
|
||||
children: vec![],
|
||||
named: hashmap!{},
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -167,20 +163,8 @@ mod tests {
|
||||
},
|
||||
text: None,
|
||||
children: vec![],
|
||||
named: hashmap!{},
|
||||
}
|
||||
],
|
||||
named: hashmap!{
|
||||
String::from("foo") => XmlElement {
|
||||
name: String::from("foo"),
|
||||
attrs: hashmap!{
|
||||
String::from("x") => String::from("1"),
|
||||
},
|
||||
text: None,
|
||||
children: vec![],
|
||||
named: hashmap!{},
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -203,20 +187,8 @@ mod tests {
|
||||
},
|
||||
text: Some(String::from("hello world")),
|
||||
children: vec![],
|
||||
named: hashmap!{},
|
||||
}
|
||||
],
|
||||
named: hashmap!{
|
||||
String::from("foo") => XmlElement {
|
||||
name: String::from("foo"),
|
||||
attrs: hashmap!{
|
||||
String::from("x") => String::from("1"),
|
||||
},
|
||||
text: Some(String::from("hello world")),
|
||||
children: vec![],
|
||||
named: hashmap!{},
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user