1use libc::{c_char, c_void};
4use std::cell::RefCell;
5use std::collections::{HashMap, HashSet};
6use std::error::Error;
7use std::ffi::{CStr, CString};
8use std::hash::{Hash, Hasher};
9use std::ptr;
10use std::rc::Rc;
11use std::str;
12
13use crate::bindings::*;
14use crate::c_helpers::*;
15use crate::tree::namespace::Namespace;
16use crate::tree::nodetype::NodeType;
17use crate::tree::{Document, DocumentRef, DocumentWeak};
18use crate::xpath::Context;
19
20pub static mut NODE_RC_MAX_GUARD: usize = 2;
22
23pub fn set_node_rc_guard(value: usize) {
26 unsafe {
27 NODE_RC_MAX_GUARD = value;
28 }
29}
30
31type NodeRef = Rc<RefCell<_Node>>;
32
33#[derive(Debug)]
34struct _Node {
35 node_ptr: xmlNodePtr,
37 document: DocumentWeak,
39 unlinked: bool,
41}
42
43#[derive(Clone, Debug)]
45pub struct Node(NodeRef);
46
47impl Hash for Node {
48 fn hash<H: Hasher>(&self, state: &mut H) {
50 self.node_ptr().hash(state);
51 }
52}
53
54impl PartialEq for Node {
55 fn eq(&self, other: &Node) -> bool {
57 std::ptr::eq(self.node_ptr(), other.node_ptr())
58 }
59}
60
61impl Eq for Node {}
62
63impl Drop for _Node {
64 fn drop(&mut self) {
67 if self.unlinked {
68 let node_ptr = self.node_ptr;
69 if !node_ptr.is_null() {
70 unsafe {
71 xmlFreeNode(node_ptr);
72 }
73 }
74 }
75 }
76}
77
78impl Node {
79 pub fn new(name: &str, ns: Option<Namespace>, doc: &Document) -> Result<Self, ()> {
81 let c_name = CString::new(name).unwrap();
84 let ns_ptr = match ns {
85 None => ptr::null_mut(),
86 Some(ns) => ns.ns_ptr(),
87 };
88 unsafe {
89 let node = xmlNewDocRawNode(
90 doc.doc_ptr(),
91 ns_ptr,
92 c_name.as_bytes().as_ptr(),
93 ptr::null(),
94 );
95 if node.is_null() {
96 Err(())
97 } else {
98 Ok(Node::wrap_new(node, &doc.0))
99 }
100 }
101 }
102
103 pub fn node_ptr(&self) -> xmlNodePtr {
105 self.0.borrow().node_ptr
106 }
107
108 pub fn node_ptr_mut(&mut self) -> Result<xmlNodePtr, String> {
111 let weak_count = Rc::weak_count(&self.0);
112 let strong_count = Rc::strong_count(&self.0);
113
114 let guard_ok = unsafe { weak_count == 0 && strong_count <= NODE_RC_MAX_GUARD };
119 if guard_ok {
120 Ok(self.0.borrow_mut().node_ptr)
121 } else {
122 Err(format!(
123 "Can not mutably reference a shared Node {:?}! Rc: weak count: {:?}; strong count: {:?}",
124 self.get_name(),
125 weak_count,
126 strong_count,
127 ))
128 }
129 }
130
131 fn _wrap(node_ptr: xmlNodePtr, unlinked: bool, document: &DocumentRef) -> Node {
133 if let Some(node) = document.borrow().get_node(node_ptr) {
135 return node.clone();
136 }
137 let node = _Node {
139 node_ptr,
140 document: Rc::downgrade(document),
141 unlinked,
142 };
143 let wrapped_node = Node(Rc::new(RefCell::new(node)));
144 document
145 .borrow_mut()
146 .insert_node(node_ptr, wrapped_node.clone());
147 wrapped_node
148 }
149 pub(crate) fn wrap(node_ptr: xmlNodePtr, document: &DocumentRef) -> Node {
151 Node::_wrap(node_ptr, false, document)
152 }
153 pub(crate) fn wrap_new(node_ptr: xmlNodePtr, document: &DocumentRef) -> Node {
155 Node::_wrap(node_ptr, true, document)
156 }
157
158 pub fn new_text(content: &str, doc: &Document) -> Result<Self, ()> {
160 let c_content = CString::new(content).unwrap();
162 unsafe {
163 let node = xmlNewDocText(doc.doc_ptr(), c_content.as_bytes().as_ptr());
164 if node.is_null() {
165 Err(())
166 } else {
167 Ok(Node::wrap_new(node, &doc.0))
168 }
169 }
170 }
171 pub fn mock(doc: &Document) -> Self {
173 Node::new("mock", None, doc).unwrap()
174 }
175
176 pub fn null() -> Self {
178 Node(Rc::new(RefCell::new(_Node {
179 node_ptr: ptr::null_mut(),
180 document: Rc::downgrade(&Document::null_ref()),
181 unlinked: true,
182 })))
183 }
184
185 pub fn to_hashable(&self) -> usize {
187 self.node_ptr() as usize
188 }
189
190 pub(crate) fn get_docref(&self) -> DocumentWeak {
191 self.0.borrow().document.clone()
192 }
193
194 pub fn get_next_sibling(&self) -> Option<Node> {
196 let ptr = xmlNextSibling(self.node_ptr());
197 self.ptr_as_option(ptr)
198 }
199
200 pub fn get_prev_sibling(&self) -> Option<Node> {
202 let ptr = xmlPrevSibling(self.node_ptr());
203 self.ptr_as_option(ptr)
204 }
205
206 pub fn get_first_child(&self) -> Option<Node> {
208 let ptr = xmlGetFirstChild(self.node_ptr());
209 self.ptr_as_option(ptr)
210 }
211 pub fn get_last_child(&self) -> Option<Node> {
213 let ptr = unsafe { xmlGetLastChild(self.node_ptr()) };
214 self.ptr_as_option(ptr)
215 }
216
217 pub fn get_next_element_sibling(&self) -> Option<Node> {
219 match self.get_next_sibling() {
220 None => None,
221 Some(child) => {
222 let mut current_node = child;
223 while !current_node.is_element_node() {
224 if let Some(sibling) = current_node.get_next_sibling() {
225 current_node = sibling;
226 } else {
227 break;
228 }
229 }
230 if current_node.is_element_node() {
231 Some(current_node)
232 } else {
233 None
234 }
235 }
236 }
237 }
238
239 pub fn get_prev_element_sibling(&self) -> Option<Node> {
241 match self.get_prev_sibling() {
242 None => None,
243 Some(child) => {
244 let mut current_node = child;
245 while !current_node.is_element_node() {
246 if let Some(sibling) = current_node.get_prev_sibling() {
247 current_node = sibling;
248 } else {
249 break;
250 }
251 }
252 if current_node.is_element_node() {
253 Some(current_node)
254 } else {
255 None
256 }
257 }
258 }
259 }
260
261 pub fn get_first_element_child(&self) -> Option<Node> {
263 match self.get_first_child() {
264 None => None,
265 Some(child) => {
266 let mut current_node = child;
267 while !current_node.is_element_node() {
268 if let Some(sibling) = current_node.get_next_sibling() {
269 current_node = sibling;
270 } else {
271 break;
272 }
273 }
274 if current_node.is_element_node() {
275 Some(current_node)
276 } else {
277 None
278 }
279 }
280 }
281 }
282
283 pub fn get_last_element_child(&self) -> Option<Node> {
285 match self.get_last_child() {
286 None => None,
287 Some(child) => {
288 let mut current_node = child;
289 while !current_node.is_element_node() {
290 if let Some(sibling) = current_node.get_prev_sibling() {
291 current_node = sibling;
292 } else {
293 break;
294 }
295 }
296 if current_node.is_element_node() {
297 Some(current_node)
298 } else {
299 None
300 }
301 }
302 }
303 }
304
305 pub fn get_child_nodes(&self) -> Vec<Node> {
307 let mut children = Vec::new();
308 if let Some(first_child) = self.get_first_child() {
309 children.push(first_child);
310 while let Some(sibling) = children.last().unwrap().get_next_sibling() {
311 children.push(sibling)
312 }
313 }
314 children
315 }
316
317 pub fn get_child_elements(&self) -> Vec<Node> {
319 self
320 .get_child_nodes()
321 .into_iter()
322 .filter(|n| n.get_type() == Some(NodeType::ElementNode))
323 .collect::<Vec<Node>>()
324 }
325
326 pub fn get_parent(&self) -> Option<Node> {
328 let ptr = xmlGetParent(self.node_ptr());
329 self.ptr_as_option(ptr)
330 }
331
332 pub fn get_type(&self) -> Option<NodeType> {
334 NodeType::from_int(xmlGetNodeType(self.node_ptr()))
335 }
336
337 pub fn add_prev_sibling(
339 &mut self,
340 new_sibling: &mut Node,
341 ) -> Result<(), Box<dyn Error + Send + Sync>> {
342 new_sibling.set_linked();
343 unsafe {
344 if xmlAddPrevSibling(self.node_ptr_mut()?, new_sibling.node_ptr_mut()?).is_null() {
345 Err(From::from("add_prev_sibling returned NULL"))
346 } else {
347 Ok(())
348 }
349 }
350 }
351
352 pub fn add_next_sibling(
354 &mut self,
355 new_sibling: &mut Node,
356 ) -> Result<(), Box<dyn Error + Send + Sync>> {
357 new_sibling.set_linked();
358 unsafe {
359 if xmlAddNextSibling(self.node_ptr_mut()?, new_sibling.node_ptr_mut()?).is_null() {
360 Err(From::from("add_next_sibling returned NULL"))
361 } else {
362 Ok(())
363 }
364 }
365 }
366
367 pub fn is_text_node(&self) -> bool {
369 self.get_type() == Some(NodeType::TextNode)
370 }
371
372 pub fn is_element_node(&self) -> bool {
374 self.get_type() == Some(NodeType::ElementNode)
375 }
376
377 pub fn is_null(&self) -> bool {
379 self.node_ptr().is_null()
380 }
381
382 pub fn get_name(&self) -> String {
384 let name_ptr = xmlNodeGetName(self.node_ptr());
385 if name_ptr.is_null() {
386 return String::new();
387 } let c_string = unsafe { CStr::from_ptr(name_ptr) };
389 c_string.to_string_lossy().into_owned()
390 }
391
392 pub fn set_name(&mut self, name: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
394 let c_name = CString::new(name).unwrap();
395 unsafe { xmlNodeSetName(self.node_ptr_mut()?, c_name.as_bytes().as_ptr()) }
396 Ok(())
397 }
398
399 pub fn get_content(&self) -> String {
402 let content_ptr = unsafe { xmlNodeGetContent(self.node_ptr()) };
403 if content_ptr.is_null() {
404 return String::new();
406 }
407 let c_string = unsafe { CStr::from_ptr(content_ptr as *const c_char) };
408 let rust_utf8 = c_string.to_string_lossy().into_owned();
409 bindgenFree(content_ptr as *mut c_void);
410 rust_utf8
411 }
412
413 pub fn set_content(&mut self, content: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
415 let c_content = CString::new(content).unwrap();
416 unsafe { xmlNodeSetContent(self.node_ptr_mut()?, c_content.as_bytes().as_ptr()); }
417 Ok(())
418 }
419
420 pub fn get_property(&self, name: &str) -> Option<String> {
422 let c_name = CString::new(name).unwrap();
423 let value_ptr = unsafe { xmlGetProp(self.node_ptr(), c_name.as_bytes().as_ptr()) };
424 if value_ptr.is_null() {
425 return None;
426 }
427 let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
428 let prop_str = c_value_string.to_string_lossy().into_owned();
429 bindgenFree(value_ptr as *mut c_void);
430 Some(prop_str)
431 }
432
433 pub fn get_property_ns(&self, name: &str, ns: &str) -> Option<String> {
435 let c_name = CString::new(name).unwrap();
436 let c_ns = CString::new(ns).unwrap();
437 let value_ptr = unsafe {
438 xmlGetNsProp(
439 self.node_ptr(),
440 c_name.as_bytes().as_ptr(),
441 c_ns.as_bytes().as_ptr(),
442 )
443 };
444 if value_ptr.is_null() {
445 return None;
446 }
447 let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
448 let prop_str = c_value_string.to_string_lossy().into_owned();
449 bindgenFree(value_ptr as *mut c_void);
450 Some(prop_str)
451 }
452
453 pub fn get_property_no_ns(&self, name: &str) -> Option<String> {
455 let c_name = CString::new(name).unwrap();
456 let value_ptr = unsafe { xmlGetNoNsProp(self.node_ptr(), c_name.as_bytes().as_ptr()) };
457 if value_ptr.is_null() {
458 return None;
459 }
460 let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
461 let prop_str = c_value_string.to_string_lossy().into_owned();
462 bindgenFree(value_ptr as *mut c_void);
463 Some(prop_str)
464 }
465
466 pub fn get_property_node(&self, name: &str) -> Option<Node> {
468 let c_name = CString::new(name).unwrap();
469 unsafe {
470 let attr_node = xmlHasProp(self.node_ptr(), c_name.as_bytes().as_ptr());
471 self.ptr_as_option(attr_node as xmlNodePtr)
472 }
473 }
474
475 pub fn get_property_node_ns(&self, name: &str, ns: &str) -> Option<Node> {
477 let c_name = CString::new(name).unwrap();
478 let c_ns = CString::new(ns).unwrap();
479 let attr_node = unsafe {
480 xmlHasNsProp(
481 self.node_ptr(),
482 c_name.as_bytes().as_ptr(),
483 c_ns.as_bytes().as_ptr(),
484 )
485 };
486 self.ptr_as_option(attr_node as xmlNodePtr)
487 }
488
489 pub fn get_property_node_no_ns(&self, name: &str) -> Option<Node> {
491 let c_name = CString::new(name).unwrap();
492 let attr_node =
493 unsafe { xmlHasNsProp(self.node_ptr(), c_name.as_bytes().as_ptr(), ptr::null()) };
494 self.ptr_as_option(attr_node as xmlNodePtr)
495 }
496
497 pub fn has_property(&self, name: &str) -> bool {
499 let c_name = CString::new(name).unwrap();
500 let value_ptr = unsafe { xmlHasProp(self.node_ptr(), c_name.as_bytes().as_ptr()) };
501 !value_ptr.is_null()
502 }
503
504 pub fn has_property_ns(&self, name: &str, ns: &str) -> bool {
506 let c_name = CString::new(name).unwrap();
507 let c_ns = CString::new(ns).unwrap();
508 let value_ptr = unsafe {
509 xmlHasNsProp(
510 self.node_ptr(),
511 c_name.as_bytes().as_ptr(),
512 c_ns.as_bytes().as_ptr(),
513 )
514 };
515 !value_ptr.is_null()
516 }
517
518 pub fn has_property_no_ns(&self, name: &str) -> bool {
520 let c_name = CString::new(name).unwrap();
521 let value_ptr =
522 unsafe { xmlHasNsProp(self.node_ptr(), c_name.as_bytes().as_ptr(), ptr::null()) };
523 !value_ptr.is_null()
524 }
525
526 pub fn has_attribute(&self, name: &str) -> bool {
528 self.has_property(name)
529 }
530 pub fn has_attribute_ns(&self, name: &str, ns: &str) -> bool {
532 self.has_property_ns(name, ns)
533 }
534
535 pub fn has_attribute_no_ns(&self, name: &str) -> bool {
537 self.has_property_no_ns(name)
538 }
539
540 pub fn set_property(
542 &mut self,
543 name: &str,
544 value: &str,
545 ) -> Result<(), Box<dyn Error + Send + Sync>> {
546 let c_name = CString::new(name).unwrap();
547 let c_value = CString::new(value).unwrap();
548 unsafe {
549 xmlSetProp(
550 self.node_ptr_mut()?,
551 c_name.as_bytes().as_ptr(),
552 c_value.as_bytes().as_ptr(),
553 )
554 };
555 Ok(())
556 }
557 pub fn set_property_ns(
559 &mut self,
560 name: &str,
561 value: &str,
562 ns: &Namespace,
563 ) -> Result<(), Box<dyn Error + Send + Sync>> {
564 let c_name = CString::new(name).unwrap();
565 let c_value = CString::new(value).unwrap();
566 unsafe {
567 xmlSetNsProp(
568 self.node_ptr_mut()?,
569 ns.ns_ptr(),
570 c_name.as_bytes().as_ptr(),
571 c_value.as_bytes().as_ptr(),
572 )
573 };
574 Ok(())
575 }
576
577 pub fn remove_property(&mut self, name: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
579 let c_name = CString::new(name).unwrap();
580 unsafe {
581 let attr_node = xmlHasProp(self.node_ptr_mut()?, c_name.as_bytes().as_ptr());
582 if !attr_node.is_null() {
583 let remove_prop_status = xmlRemoveProp(attr_node);
584 if remove_prop_status == 0 {
585 Ok(())
586 } else {
587 Err(From::from(format!(
589 "libxml2 failed to remove property with status: {remove_prop_status:?}")))
590 }
591 } else {
592 Ok(())
594 }
595 }
596 }
597
598 pub fn remove_property_ns(
600 &mut self,
601 name: &str,
602 ns: &str,
603 ) -> Result<(), Box<dyn Error + Send + Sync>> {
604 let c_name = CString::new(name).unwrap();
605 let c_ns = CString::new(ns).unwrap();
606 unsafe {
607 let attr_node = xmlHasNsProp(
608 self.node_ptr_mut()?,
609 c_name.as_bytes().as_ptr(),
610 c_ns.as_bytes().as_ptr(),
611 );
612 if !attr_node.is_null() {
613 let remove_prop_status = xmlRemoveProp(attr_node);
614 if remove_prop_status == 0 {
615 Ok(())
616 } else {
617 Err(From::from(format!(
619 "libxml2 failed to remove property with status: {remove_prop_status:?}")))
620 }
621 } else {
622 Ok(())
624 }
625 }
626 }
627
628 pub fn remove_property_no_ns(&mut self, name: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
630 let c_name = CString::new(name).unwrap();
631 let attr_node = unsafe {
632 xmlHasNsProp(
633 self.node_ptr_mut()?,
634 c_name.as_bytes().as_ptr(),
635 ptr::null(),
636 )
637 };
638 if !attr_node.is_null() {
639 let remove_prop_status = unsafe { xmlRemoveProp(attr_node) };
640 if remove_prop_status == 0 {
641 Ok(())
642 } else {
643 Err(From::from(format!(
645 "libxml2 failed to remove property with status: {remove_prop_status:?}")))
646 }
647 } else {
648 Ok(())
650 }
651 }
652
653 pub fn get_attribute(&self, name: &str) -> Option<String> {
655 self.get_property(name)
656 }
657
658 pub fn get_attribute_ns(&self, name: &str, ns: &str) -> Option<String> {
660 self.get_property_ns(name, ns)
661 }
662
663 pub fn get_attribute_no_ns(&self, name: &str) -> Option<String> {
665 self.get_property_no_ns(name)
666 }
667
668 pub fn get_attribute_node(&self, name: &str) -> Option<Node> {
670 self.get_property_node(name)
671 }
672
673 pub fn get_attribute_node_ns(&self, name: &str, ns: &str) -> Option<Node> {
675 self.get_property_node_ns(name, ns)
676 }
677
678 pub fn get_attribute_node_no_ns(&self, name: &str) -> Option<Node> {
680 self.get_property_node_no_ns(name)
681 }
682
683 pub fn set_attribute(
685 &mut self,
686 name: &str,
687 value: &str,
688 ) -> Result<(), Box<dyn Error + Send + Sync>> {
689 self.set_property(name, value)
690 }
691 pub fn set_attribute_ns(
693 &mut self,
694 name: &str,
695 value: &str,
696 ns: &Namespace,
697 ) -> Result<(), Box<dyn Error + Send + Sync>> {
698 self.set_property_ns(name, value, ns)
699 }
700
701 pub fn remove_attribute(&mut self, name: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
703 self.remove_property(name)
704 }
705
706 pub fn remove_attribute_ns(
708 &mut self,
709 name: &str,
710 ns: &str,
711 ) -> Result<(), Box<dyn Error + Send + Sync>> {
712 self.remove_property_ns(name, ns)
713 }
714
715 pub fn remove_attribute_no_ns(&mut self, name: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
717 self.remove_property_no_ns(name)
718 }
719
720 pub fn get_properties(&self) -> HashMap<String, String> {
722 let mut attributes = HashMap::new();
723
724 let mut current_prop = xmlGetFirstProperty(self.node_ptr());
725 while !current_prop.is_null() {
726 let name_ptr = xmlAttrName(current_prop);
727 let c_name_string = unsafe { CStr::from_ptr(name_ptr) };
728 let name = c_name_string.to_string_lossy().into_owned();
729 let value = self.get_property(&name).unwrap_or_default();
730 attributes.insert(name, value);
731 current_prop = xmlNextPropertySibling(current_prop);
732 }
733
734 attributes
735 }
736
737 pub fn get_properties_ns(&self) -> HashMap<(String, Option<Namespace>), String> {
739 let mut attributes = HashMap::new();
740
741 let mut current_prop = xmlGetFirstProperty(self.node_ptr());
742 while !current_prop.is_null() {
743 let name_ptr = xmlAttrName(current_prop);
744 let c_name_string = unsafe { CStr::from_ptr(name_ptr) };
745 let name = c_name_string.to_string_lossy().into_owned();
746 let ns_ptr = xmlAttrNs(current_prop);
747 if ns_ptr.is_null() {
748 let value = self.get_property_no_ns(&name).unwrap_or_default();
749 attributes.insert((name, None), value);
750 } else {
751 let ns = Namespace { ns_ptr };
752 let value = self
753 .get_property_ns(&name, &ns.get_href())
754 .unwrap_or_default();
755 attributes.insert((name, Some(ns)), value);
756 }
757 current_prop = xmlNextPropertySibling(current_prop);
758 }
759
760 attributes
761 }
762
763 pub fn get_attributes(&self) -> HashMap<String, String> {
765 self.get_properties()
766 }
767
768 pub fn get_attributes_ns(&self) -> HashMap<(String, Option<Namespace>), String> {
770 self.get_properties_ns()
771 }
772
773 pub fn get_namespace(&self) -> Option<Namespace> {
775 let ns_ptr = xmlNodeNs(self.node_ptr());
776 if ns_ptr.is_null() {
777 None
778 } else {
779 Some(Namespace { ns_ptr })
780 }
781 }
782
783 pub fn get_namespaces(&self, doc: &Document) -> Vec<Namespace> {
785 let list_ptr_raw = unsafe { xmlGetNsList(doc.doc_ptr(), self.node_ptr()) };
786 if list_ptr_raw.is_null() {
787 Vec::new()
788 } else {
789 let mut namespaces = Vec::new();
790 let mut ptr_iter = list_ptr_raw as *mut xmlNsPtr;
791 unsafe {
792 while !ptr_iter.is_null() && !(*ptr_iter).is_null() {
793 namespaces.push(Namespace { ns_ptr: *ptr_iter });
794 ptr_iter = ptr_iter.add(1);
795 }
796 }
809 namespaces
810 }
811 }
812
813 pub fn get_namespace_declarations(&self) -> Vec<Namespace> {
815 if self.get_type() != Some(NodeType::ElementNode) {
816 return Vec::new();
818 }
819 let mut namespaces = Vec::new();
820 let mut ns_ptr = xmlNodeNsDeclarations(self.node_ptr());
821 while !ns_ptr.is_null() {
822 if !xmlNsPrefix(ns_ptr).is_null() || !xmlNsHref(ns_ptr).is_null() {
823 namespaces.push(Namespace { ns_ptr });
824 }
825 ns_ptr = xmlNextNsSibling(ns_ptr);
826 }
827 namespaces
828 }
829
830 pub fn set_namespace(
832 &mut self,
833 namespace: &Namespace,
834 ) -> Result<(), Box<dyn Error + Send + Sync>> {
835 unsafe {
836 xmlSetNs(self.node_ptr_mut()?, namespace.ns_ptr());
837 }
838 Ok(())
839 }
840
841 pub fn lookup_namespace_prefix(&self, href: &str) -> Option<String> {
843 if href.is_empty() {
844 return None;
845 }
846 let c_href = CString::new(href).unwrap();
847 unsafe {
848 let ptr_mut = self.node_ptr();
849 let ns_ptr = xmlSearchNsByHref(xmlGetDoc(ptr_mut), ptr_mut, c_href.as_bytes().as_ptr());
850 if !ns_ptr.is_null() {
851 let ns = Namespace { ns_ptr };
852 let ns_prefix = ns.get_prefix();
853 Some(ns_prefix)
854 } else {
855 None
856 }
857 }
858 }
859
860 pub fn lookup_namespace_uri(&self, prefix: &str) -> Option<String> {
862 if prefix.is_empty() {
863 return None;
864 }
865 let c_prefix = CString::new(prefix).unwrap();
866 unsafe {
867 let ns_ptr = xmlSearchNs(
868 xmlGetDoc(self.node_ptr()),
869 self.node_ptr(),
870 c_prefix.as_bytes().as_ptr(),
871 );
872 if !ns_ptr.is_null() {
873 let ns = Namespace { ns_ptr };
874 let ns_prefix = ns.get_href();
875 if !ns_prefix.is_empty() {
876 Some(ns_prefix)
877 } else {
878 None
879 }
880 } else {
881 None
882 }
883 }
884 }
885
886 pub fn recursively_remove_namespaces(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
889 xmlNodeRecursivelyRemoveNs(self.node_ptr_mut()?);
890 Ok(())
891 }
892
893 pub fn get_class_names(&self) -> HashSet<String> {
895 let mut set = HashSet::new();
896 if let Some(value) = self.get_property("class") {
897 for n in value.split(' ') {
898 set.insert(n.to_owned());
899 }
900 }
901 set
902 }
903
904 pub fn add_child(&mut self, child: &mut Node) -> Result<(), String> {
906 child.set_linked();
907 unsafe {
908 let new_child_ptr = xmlAddChild(self.node_ptr_mut()?, child.node_ptr_mut()?);
909 if new_child_ptr.is_null() {
910 Err("add_child encountered NULL pointer".to_string())
911 } else {
912 Ok(())
913 }
914 }
915 }
916
917 pub fn new_child(
919 &mut self,
920 ns: Option<Namespace>,
921 name: &str,
922 ) -> Result<Node, Box<dyn Error + Send + Sync>> {
923 let c_name = CString::new(name).unwrap();
924 let ns_ptr = match ns {
925 None => ptr::null_mut(),
926 Some(mut ns) => ns.ns_ptr_mut(),
927 };
928 unsafe {
929 let new_ptr = xmlNewChild(
930 self.node_ptr_mut()?,
931 ns_ptr,
932 c_name.as_bytes().as_ptr(),
933 ptr::null(),
934 );
935 Ok(Node::wrap(new_ptr, &self.get_docref().upgrade().unwrap()))
936 }
937 }
938
939 pub fn add_text_child(
941 &mut self,
942 ns: Option<Namespace>,
943 name: &str,
944 content: &str,
945 ) -> Result<Node, Box<dyn Error + Send + Sync>> {
946 let c_name = CString::new(name).unwrap();
947 let c_content = CString::new(content).unwrap();
948 let ns_ptr = match ns {
949 None => ptr::null_mut(),
950 Some(mut ns) => ns.ns_ptr_mut(),
951 };
952 unsafe {
953 let new_ptr = xmlNewTextChild(
954 self.node_ptr_mut()?,
955 ns_ptr,
956 c_name.as_bytes().as_ptr(),
957 c_content.as_bytes().as_ptr(),
958 );
959 Ok(Node::wrap(new_ptr, &self.get_docref().upgrade().unwrap()))
960 }
961 }
962
963 pub fn append_text(&mut self, content: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
965 let c_len = content.len() as i32;
966 if c_len > 0 {
967 let c_content = CString::new(content).unwrap();
968 unsafe {
969 xmlNodeAddContentLen(self.node_ptr_mut()?, c_content.as_bytes().as_ptr(), c_len);
970 }
971 }
972 Ok(())
973 }
974
975 pub fn unlink_node(&mut self) {
980 let node_type = self.get_type();
981 if node_type != Some(NodeType::DocumentNode)
982 && node_type != Some(NodeType::DocumentFragNode)
983 && !self.is_unlinked()
984 {
985 self.set_unlinked();
987 unsafe {
988 xmlUnlinkNode(self.node_ptr());
989 }
990 }
991 }
992 pub fn unlink(&mut self) {
994 self.unlink_node()
995 }
996 pub fn unbind_node(&mut self) {
998 self.unlink_node()
999 }
1000 pub fn unbind(&mut self) {
1002 self.unlink_node()
1003 }
1004
1005 pub fn is_unlinked(&self) -> bool {
1007 self.0.borrow().unlinked
1008 }
1009
1010 fn ptr_as_option(&self, node_ptr: xmlNodePtr) -> Option<Node> {
1011 if node_ptr.is_null() {
1012 None
1013 } else {
1014 let doc_ref = self.get_docref().upgrade().unwrap();
1015 let new_node = Node::wrap(node_ptr, &doc_ref);
1016 Some(new_node)
1017 }
1018 }
1019
1020 pub(crate) fn set_linked(&self) {
1022 self.0.borrow_mut().unlinked = false;
1023 }
1024
1025 pub(crate) fn set_unlinked(&self) {
1027 self.0.borrow_mut().unlinked = true;
1028 self
1029 .get_docref()
1030 .upgrade()
1031 .unwrap()
1032 .borrow_mut()
1033 .forget_node(self.node_ptr());
1034 }
1035
1036 pub fn findnodes(&self, xpath: &str) -> Result<Vec<Node>, ()> {
1038 let mut context = Context::from_node(self)?;
1039 context.findnodes(xpath, Some(self))
1040 }
1041
1042 pub fn findvalues(&self, xpath: &str) -> Result<Vec<String>, ()> {
1044 let mut context = Context::from_node(self)?;
1045 context.findvalues(xpath, Some(self))
1046 }
1047
1048 pub fn replace_child_node(
1051 &mut self,
1052 mut new: Node,
1053 mut old: Node,
1054 ) -> Result<Node, Box<dyn Error + Send + Sync>> {
1055 if new == old || self == &new {
1057 Ok(old)
1059 } else if self.get_type() == Some(NodeType::ElementNode) {
1060 if let Some(old_parent) = old.get_parent() {
1061 if &old_parent == self {
1062 new.unlink();
1064 old.add_next_sibling(&mut new)?;
1066 old.unlink();
1067 Ok(old)
1068 } else {
1069 Err(From::from(format!(
1070 "Old node was not a child of {:?} parent. Registered parent is {:?} instead.",
1071 self.get_name(),
1072 old_parent.get_name()
1073 )))
1074 }
1075 } else {
1076 Err(From::from(format!(
1077 "Old node was not a child of {:?} parent. No registered parent exists.",
1078 self.get_name()
1079 )))
1080 }
1081 } else {
1082 Err(From::from(
1083 "Can only call replace_child_node an a NodeType::Element type parent.",
1084 ))
1085 }
1086 }
1087}