quick-xml
quick-xml copied to clipboard
Get and Edit single attributes
Hi!
first of all thank you for your work, i truly find your library helpful and it's blazingly fast.
I am currently trying to change single attributes with this approach
elem.extend_attributes(e.attributes().map(|attr| {
let mut attr = attr.unwrap();
if attr.key == b"KEY" {
// change value
}
}
attr
}));
It does work, however i do not like this approach too much.
I tried using
elem.push_attribute(("KEY", "sAAAA"));
but it just adds another value with the same key.
Is there a way to access and edit individual xml attributes like
elem.get_value("KEY");
elem.edit_key("KEY", my_value);
Thanks!
I think I've already answered somewhere but no, there is no such capability yet. I would be happy to merge a PR if you have some time to do it.
I'd prefer more generic methods that allow dealing with duplicates.
get_value() could return an iterator instead and can easily be implemented: self.attributes().filter(|attr| attr.key == key). If just a single attribute is expected, a simple get_value().next() will get you there.
Maybe it would be interesting to have variants like get_first_or_default() and get_first_or_insert{,_with}().
An attributes_mut() function could be a generic pendant to attributes() to edit attributes,on top of which an edit_key() method also can be implemented.
I attempted a POC of that, but since you need to mutably borrow BytesStart::buf in the iterator-item to allow modification, borrowck rightly refuses that code. Otherwise you could easily do let (mut x, y) = (attrIter.next().unwrap(), attrIter.next().unwrap()); and modification of x screws up y (and also attrIter for that matter) because the indices change.
I imagine using a StreamingIterator instead of the standard Iterator could work, though we'd need a mutable variant of that.
To implement just the simple edit_key(), but still properly deal with duplicates, it could also take a closure-parameter, whose job it is to edit the attribute, e.g. elem.edit_key("KEY", |old_key, old_value| { assert_eq(old_key, "KEY"); (new_key, new_value) });.
Simultaneously checking that there are no duplicates or whatever can be done with captured variables: bool found = false; elem.edit_key("KEY", |old_key, old_value| { assert!(!found); found = true; (new_key, new_value) });.