Skip to content

Commit

Permalink
add support for has_attribute, has_attribute_ns
Browse files Browse the repository at this point in the history
  • Loading branch information
dginev committed Mar 26, 2022
1 parent 84e7b08 commit 8d0617a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
## [0.3.1] (in development)

* Added: Thanks to @lepapareil, @hurlenko and @ballsteve for contributing installation docs for Windows and MacOS.
* Added: `Node` and `RoNode` now have `has_property` (alias `has_attribute`) and `has_property_ns` (alias `has_attribute_ns`) to check attribute presence without allocating the value.

## [0.3.0] 2021-27-05

* Change `Parser::parse_file/string_with_encoding` to `Parser::parse_file/string_with_options`.
* Change `Parser::parse_file/string_with_encoding` to `Parser::parse_file/string_with_options`.

* Introduce `ParserOptions` which encapsulates the forced encoding setting together with libxml2s HTML and XML parser options.

Expand Down
23 changes: 23 additions & 0 deletions src/readonly/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,29 @@ impl RoNode {
self.get_properties()
}

/// Check if a property has been defined, without allocating its value
pub fn has_property(self, name: &str) -> bool {
let c_name = CString::new(name).unwrap();
let value_ptr = unsafe { xmlHasProp(self.0, c_name.as_bytes().as_ptr()) };
!value_ptr.is_null()
}
/// Check if property `name` in namespace `ns` exists
pub fn has_property_ns(self, name: &str, ns: &str) -> bool {
let c_name = CString::new(name).unwrap();
let c_ns = CString::new(ns).unwrap();
let value_ptr =
unsafe { xmlHasNsProp(self.0, c_name.as_bytes().as_ptr(), c_ns.as_bytes().as_ptr()) };
!value_ptr.is_null()
}
/// Alias for has_property
pub fn has_attribute(self, name: &str) -> bool {
self.has_property(name)
}
/// Alias for has_property_ns
pub fn has_attribute_ns(self, name: &str, ns: &str) -> bool {
self.has_property_ns(name, ns)
}

/// Gets the active namespace associated of this node
pub fn get_namespace(self) -> Option<Namespace> {
let ns_ptr = xmlNodeNs(self.0);
Expand Down
23 changes: 23 additions & 0 deletions src/tree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,29 @@ impl Node {
}
}

/// Check if a property has been defined, without allocating its value
pub fn has_property(&self, name: &str) -> bool {
let c_name = CString::new(name).unwrap();
let value_ptr = unsafe { xmlHasProp(self.node_ptr(), c_name.as_bytes().as_ptr()) };
!value_ptr.is_null()
}
/// Check if property `name` in namespace `ns` exists
pub fn has_property_ns(&self, name: &str, ns: &str) -> bool {
let c_name = CString::new(name).unwrap();
let c_ns = CString::new(ns).unwrap();
let value_ptr =
unsafe { xmlHasNsProp(self.node_ptr(), c_name.as_bytes().as_ptr(), c_ns.as_bytes().as_ptr()) };
!value_ptr.is_null()
}
/// Alias for has_property
pub fn has_attribute(&self, name: &str) -> bool {
self.has_property(name)
}
/// Alias for has_property_ns
pub fn has_attribute_ns(&self, name: &str, ns: &str) -> bool {
self.has_property_ns(name, ns)
}

/// Sets the value of property `name` to `value`
pub fn set_property(&mut self, name: &str, value: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
let c_name = CString::new(name).unwrap();
Expand Down
7 changes: 7 additions & 0 deletions tests/tree_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ fn node_attributes_accessor() {
assert_eq!(attributes.len(), 1);
assert_eq!(attributes.get("attribute"), Some(&"value".to_string()));

// Has
assert_eq!(child.has_attribute("attribute"), true);
// Get
assert_eq!(child.get_attribute("attribute"), Some("value".to_string()));
// Get as node
Expand All @@ -101,6 +103,7 @@ fn node_attributes_accessor() {
// Remove
assert!(child.remove_attribute("attribute").is_ok());
assert_eq!(child.get_attribute("attribute"), None);
assert_eq!(child.has_attribute("attribute"), false);
// Recount
let attributes = child.get_attributes();
assert_eq!(attributes.len(), 0);
Expand Down Expand Up @@ -239,10 +242,14 @@ fn can_manage_attributes() {
let value = "examplevalue";
let pre_value = hello_element.get_attribute(key);
assert_eq!(pre_value, None);
let pre_prop_check = hello_element.has_property(key);
assert_eq!(pre_prop_check, false);
let pre_prop_value = hello_element.get_property(key);
assert_eq!(pre_prop_value, None);

assert!(hello_element.set_attribute(key, value).is_ok());
let new_check = hello_element.has_attribute(key);
assert_eq!(new_check, true);
let new_value = hello_element.get_attribute(key);
assert_eq!(new_value, Some(value.to_owned()));
}
Expand Down

0 comments on commit 8d0617a

Please sign in to comment.