Add a function to get a named xml element

This commit is contained in:
kpcyrd
2019-05-24 17:18:21 +02:00
parent 366f864317
commit 76bc93d73b
5 changed files with 86 additions and 32 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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");

View File

@@ -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

View File

@@ -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!{},
}
},
}
]
});