Skip to content

Commit

Permalink
Add get_attribute_no_ns to Node and RoNode
Browse files Browse the repository at this point in the history
  • Loading branch information
anwaralameddin authored and dginev committed Feb 24, 2024
1 parent 11f1d4a commit 4d70951
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [0.3.4] (in development)

### Added

* Node methods: `get_property_no_ns` (alias: `get_attribute_no_ns`)

## [0.3.3] 2023-17-07

### Changed
Expand Down
21 changes: 21 additions & 0 deletions src/readonly/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,21 @@ impl RoNode {
Some(prop_str)
}

/// Returns the value of property `name` with no namespace
pub fn get_property_no_ns(self, name: &str) -> Option<String> {
let c_name = CString::new(name).unwrap();
let value_ptr = unsafe { xmlGetNoNsProp(self.0, c_name.as_bytes().as_ptr()) };
if value_ptr.is_null() {
return None;
}
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
let prop_str = c_value_string.to_string_lossy().into_owned();
unsafe {
libc::free(value_ptr as *mut c_void);
}
Some(prop_str)
}

/// Return an attribute as a `Node` struct of type AttributeNode
pub fn get_property_node(self, name: &str) -> Option<RoNode> {
let c_name = CString::new(name).unwrap();
Expand All @@ -264,11 +279,17 @@ impl RoNode {
pub fn get_attribute(self, name: &str) -> Option<String> {
self.get_property(name)
}

/// Alias for get_property_ns
pub fn get_attribute_ns(self, name: &str, ns: &str) -> Option<String> {
self.get_property_ns(name, ns)
}

/// Alias for get_property_no_ns
pub fn get_attribute_no_ns(self, name: &str) -> Option<String> {
self.get_property_no_ns(name)
}

/// Alias for get_property_node
pub fn get_attribute_node(self, name: &str) -> Option<RoNode> {
self.get_property_node(name)
Expand Down
21 changes: 21 additions & 0 deletions src/tree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,21 @@ impl Node {
Some(prop_str)
}

/// Returns the value of property `name` with no namespace
pub fn get_property_no_ns(&self, name: &str) -> Option<String> {
let c_name = CString::new(name).unwrap();
let value_ptr = unsafe { xmlGetNoNsProp(self.node_ptr(), c_name.as_bytes().as_ptr()) };
if value_ptr.is_null() {
return None;
}
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
let prop_str = c_value_string.to_string_lossy().into_owned();
unsafe {
libc::free(value_ptr as *mut c_void);
}
Some(prop_str)
}

/// Return an attribute as a `Node` struct of type AttributeNode
pub fn get_property_node(&self, name: &str) -> Option<Node> {
let c_name = CString::new(name).unwrap();
Expand Down Expand Up @@ -590,11 +605,17 @@ impl Node {
pub fn get_attribute(&self, name: &str) -> Option<String> {
self.get_property(name)
}

/// Alias for get_property_ns
pub fn get_attribute_ns(&self, name: &str, ns: &str) -> Option<String> {
self.get_property_ns(name, ns)
}

/// Alias for get_property_no_ns
pub fn get_attribute_no_ns(&self, name: &str) -> Option<String> {
self.get_property_no_ns(name)
}

/// Alias for get_property_node
pub fn get_attribute_node(&self, name: &str) -> Option<Node> {
self.get_property_node(name)
Expand Down
41 changes: 41 additions & 0 deletions tests/tree_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,47 @@ fn attribute_namespace_accessors() {
assert_eq!(fb_uri, Some("http://www.foobar.org".to_string())); // system ns has the global prefix when doing global lookup
}

#[test]
fn attribute_no_namespace() {
let mut doc = Document::new().unwrap();
let element_result = Node::new("example", None, &doc);
assert!(element_result.is_ok());

let mut element = element_result.unwrap();
doc.set_root_element(&element);

let ns_result = Namespace::new("myns", "https://www.example.com/myns", &mut element);
assert!(ns_result.is_ok());
let ns = ns_result.unwrap();
assert!(element.set_attribute_ns("foo", "ns", &ns).is_ok());

let foo_ns_attr = element.get_attribute_ns("foo", "https://www.example.com/myns");
assert!(foo_ns_attr.is_some());
assert_eq!(foo_ns_attr.unwrap(), "ns");

let foo_no_ns_attr = element.get_attribute_no_ns("foo");
assert!(foo_no_ns_attr.is_none());

assert!(element.set_attribute("foo", "no_ns").is_ok());

let foo_no_ns_attr = element.get_attribute_no_ns("foo");
assert!(foo_no_ns_attr.is_some());
assert_eq!(foo_no_ns_attr.unwrap(), "no_ns");

// TODO: include this when `remove_attribute_no_ns` is implemented
// It's not possible use remove_attribute here as it removes the first
// attribute found with the local name regardless of the namespace; here it
// removes the attribute with the namespace
// assert!(element.remove_attribute_no_ns("foo").is_ok());
// let foo_no_ns_attr = element.get_attribute_no_ns("foo");
// assert!(foo_no_ns_attr.is_none());

assert!(element.set_attribute("bar", "bar").is_ok());
let bar_no_ns_attr = element.get_attribute_no_ns("bar");
assert!(bar_no_ns_attr.is_some());
assert_eq!(bar_no_ns_attr.unwrap(), "bar");
}

#[test]
fn node_can_unbind() {
let mut doc = Document::new().unwrap();
Expand Down

0 comments on commit 4d70951

Please sign in to comment.