use std::{os::raw::c_void, ptr::null_mut};
use crate::{
libxml::globals::{xml_free, xml_malloc},
valid::{xml_add_id, xml_is_id, xml_remove_id},
};
use super::{
NodeCommon, XML_LOCAL_NAMESPACE, XmlAttr, XmlAttrPtr, XmlAttributeType, XmlDocPtr,
XmlElementType, XmlGenericNodePtr, XmlNode, XmlNodePtr, XmlNs, XmlNsPtr, xml_free_ns,
xml_get_doc_entity, xml_new_ns, xml_search_ns_by_namespace_strict,
xml_search_ns_by_prefix_strict, xml_tree_err_memory, xml_tree_nslist_lookup_by_prefix,
};
#[doc(alias = "xmlDOMWrapAcquireNsFunction")]
pub type XmlDOMWrapAcquireNsFunction = unsafe fn(
ctxt: XmlDOMWrapCtxtPtr,
node: Option<XmlGenericNodePtr>,
ns_name: Option<&str>,
ns_prefix: Option<&str>,
) -> Option<XmlNsPtr>;
pub type XmlDOMWrapCtxtPtr = *mut XmlDOMWrapCtxt;
#[repr(C)]
pub struct XmlDOMWrapCtxt {
pub(super) _private: *mut c_void,
pub(super) typ: i32,
pub(super) namespace_map: *mut c_void,
pub(super) get_ns_for_node_func: Option<XmlDOMWrapAcquireNsFunction>,
}
impl Default for XmlDOMWrapCtxt {
fn default() -> Self {
Self {
_private: null_mut(),
typ: 0,
namespace_map: null_mut(),
get_ns_for_node_func: None,
}
}
}
pub type XmlNsMapItemPtr = *mut XmlNsMapItem;
#[repr(C)]
pub struct XmlNsMapItem {
next: XmlNsMapItemPtr,
prev: XmlNsMapItemPtr,
old_ns: Option<XmlNsPtr>,
new_ns: Option<XmlNsPtr>,
shadow_depth: i32,
depth: i32,
}
impl Default for XmlNsMapItem {
fn default() -> Self {
Self {
next: null_mut(),
prev: null_mut(),
old_ns: None,
new_ns: None,
shadow_depth: 0,
depth: 0,
}
}
}
pub type XmlNsMapPtr = *mut XmlNsMap;
#[repr(C)]
pub struct XmlNsMap {
first: XmlNsMapItemPtr,
last: XmlNsMapItemPtr,
pool: XmlNsMapItemPtr,
}
impl Default for XmlNsMap {
fn default() -> Self {
Self {
first: null_mut(),
last: null_mut(),
pool: null_mut(),
}
}
}
#[doc(alias = "xmlDOMWrapNewCtxt")]
pub unsafe fn xml_dom_wrap_new_ctxt() -> XmlDOMWrapCtxtPtr {
unsafe {
let ret: XmlDOMWrapCtxtPtr = xml_malloc(size_of::<XmlDOMWrapCtxt>()) as _;
if ret.is_null() {
xml_tree_err_memory("allocating DOM-wrapper context");
return null_mut();
}
std::ptr::write(&mut *ret, XmlDOMWrapCtxt::default());
ret
}
}
#[doc(alias = "xmlDOMWrapNsMapFree")]
unsafe fn xml_dom_wrap_ns_map_free(nsmap: XmlNsMapPtr) {
unsafe {
let mut cur: XmlNsMapItemPtr;
let mut tmp: XmlNsMapItemPtr;
if nsmap.is_null() {
return;
}
cur = (*nsmap).pool;
while !cur.is_null() {
tmp = cur;
cur = (*cur).next;
xml_free(tmp as _);
}
cur = (*nsmap).first;
while !cur.is_null() {
tmp = cur;
cur = (*cur).next;
xml_free(tmp as _);
}
xml_free(nsmap as _);
}
}
#[doc(alias = "xmlDOMWrapFreeCtxt")]
pub unsafe fn xml_dom_wrap_free_ctxt(ctxt: XmlDOMWrapCtxtPtr) {
unsafe {
if ctxt.is_null() {
return;
}
if !(*ctxt).namespace_map.is_null() {
xml_dom_wrap_ns_map_free((*ctxt).namespace_map as _);
}
xml_free(ctxt as _);
}
}
macro_rules! XML_NSMAP_NOTEMPTY {
($m:expr) => {
!$m.is_null() && !(*$m).first.is_null()
};
}
macro_rules! XML_NSMAP_FOREACH {
($m:expr, $i:expr, $b:block) => {
let mut __initialized = false;
$i = (*$m).first;
while {
if !__initialized {
__initialized = true;
} else {
$i = (*$i).next;
}
!$i.is_null()
} {
$b;
}
};
}
macro_rules! XML_NSMAP_POP {
($m:expr, $i:expr) => {
$i = (*$m).last;
(*$m).last = (*$i).prev;
if (*$m).last.is_null() {
(*$m).first = null_mut();
} else {
(*(*$m).last).next = null_mut();
}
(*$i).next = (*$m).pool;
(*$m).pool = $i;
};
}
#[repr(C)]
enum XmlDomreconcileNsoptions {
XmlDomReconnsRemoveredund = 1 << 0,
}
const XML_TREE_NSMAP_PARENT: i32 = -1;
const XML_TREE_NSMAP_DOC: i32 = -3;
const XML_TREE_NSMAP_CUSTOM: i32 = -4;
#[doc(alias = "xmlDOMWrapNsMapAddItem")]
unsafe fn xml_dom_wrap_ns_map_add_item(
nsmap: *mut XmlNsMapPtr,
position: i32,
old_ns: Option<XmlNsPtr>,
new_ns: Option<XmlNsPtr>,
depth: i32,
) -> XmlNsMapItemPtr {
unsafe {
let ret: XmlNsMapItemPtr;
let mut map: XmlNsMapPtr;
if nsmap.is_null() {
return null_mut();
}
if position != -1 && position != 0 {
return null_mut();
}
map = *nsmap;
if map.is_null() {
map = xml_malloc(size_of::<XmlNsMap>()) as _;
if map.is_null() {
xml_tree_err_memory("allocating namespace map");
return null_mut();
}
std::ptr::write(&mut *map, XmlNsMap::default());
*nsmap = map;
}
if !(*map).pool.is_null() {
ret = (*map).pool;
(*map).pool = (*ret).next;
std::ptr::write(&mut *ret, XmlNsMapItem::default());
} else {
ret = xml_malloc(size_of::<XmlNsMapItem>()) as _;
if ret.is_null() {
xml_tree_err_memory("allocating namespace map item");
return null_mut();
}
std::ptr::write(&mut *ret, XmlNsMapItem::default());
}
if (*map).first.is_null() {
(*map).first = ret;
(*map).last = ret;
} else if position == -1 {
(*ret).prev = (*map).last;
(*(*map).last).next = ret;
(*map).last = ret;
} else if position == 0 {
(*(*map).first).prev = ret;
(*ret).next = (*map).first;
(*map).first = ret;
}
(*ret).old_ns = old_ns;
(*ret).new_ns = new_ns;
(*ret).shadow_depth = -1;
(*ret).depth = depth;
ret
}
}
#[doc(alias = "xmlDOMWrapNSNormGatherInScopeNs")]
unsafe fn xml_dom_wrap_ns_norm_gather_in_scope_ns(
map: *mut XmlNsMapPtr,
node: Option<XmlGenericNodePtr>,
) -> i32 {
unsafe {
let mut mi: XmlNsMapItemPtr;
let mut shadowed: i32;
if map.is_null() || !(*map).is_null() {
return -1;
}
let Some(node) = node else {
return -1;
};
let mut cur = Some(node);
while let Some(cur_node) =
cur.filter(|&cur| Some(cur) != cur.document().map(|doc| doc.into()))
{
if let Ok(cur_node) = XmlNodePtr::try_from(cur_node) {
if matches!(cur_node.element_type(), XmlElementType::XmlElementNode)
&& cur_node.ns_def.is_some()
{
let mut ns = cur_node.ns_def;
while let Some(now) = ns {
shadowed = 0;
if XML_NSMAP_NOTEMPTY!(*map) {
XML_NSMAP_FOREACH!(*map, mi, {
if now.prefix() == (*mi).new_ns.unwrap().prefix() {
shadowed = 1;
break;
}
});
}
mi = xml_dom_wrap_ns_map_add_item(
map,
0,
None,
Some(now),
XML_TREE_NSMAP_PARENT,
);
if mi.is_null() {
return -1;
}
if shadowed != 0 {
(*mi).shadow_depth = 0;
}
ns = now.next;
}
}
}
cur = cur_node.parent();
}
0
}
}
#[doc(alias = "xmlDOMWrapNSNormAddNsMapItem2")]
unsafe fn xml_dom_wrap_ns_norm_add_ns_map_item2(
list: &mut Vec<XmlNsPtr>,
number: *mut i32,
old_ns: XmlNsPtr,
new_ns: XmlNsPtr,
) -> i32 {
unsafe {
list.push(old_ns);
list.push(new_ns);
(*number) += 1;
0
}
}
#[doc(alias = "xmlDOMWrapStoreNs")]
fn xml_dom_wrap_store_ns(
mut doc: XmlDocPtr,
ns_name: Option<&str>,
prefix: Option<&str>,
) -> Option<XmlNsPtr> {
let mut ns = doc.ensure_xmldecl()?;
if let Some(next) = ns.next {
if next.prefix().as_deref() == prefix && next.href.as_deref() == ns_name {
return Some(next);
}
ns = next;
while let Some(next) = ns.next {
if next.prefix().as_deref() == prefix && next.href.as_deref() == ns_name {
return Some(next);
}
ns = next;
}
}
ns.next = xml_new_ns(None, ns_name, prefix);
ns.next
}
#[doc(alias = "xmlDOMWrapNSNormDeclareNsForced")]
fn xml_dom_wrap_nsnorm_declare_ns_forced(
doc: XmlDocPtr,
mut elem: XmlNodePtr,
ns_name: Option<&str>,
prefix: Option<&str>,
check_shadow: i32,
) -> Option<XmlNsPtr> {
let mut counter: i32 = 0;
if !matches!(elem.element_type(), XmlElementType::XmlElementNode) {
return None;
}
let mut pref = prefix.map(|prefix| prefix.to_owned());
loop {
if elem.ns_def.is_some()
&& xml_tree_nslist_lookup_by_prefix(elem.ns_def, pref.as_deref()).is_some()
{
} else {
if check_shadow != 0
&& elem
.parent()
.filter(|&p| {
Some(p) != p.document().map(|doc| doc.into())
&& xml_search_ns_by_prefix_strict(doc, p, pref.as_deref(), None) == 1
})
.is_some()
{
} else {
let ret = xml_new_ns(None, ns_name, pref.as_deref())?;
if let Some(ns_def) = elem.ns_def {
let mut ns2 = ns_def;
while let Some(next) = ns2.next {
ns2 = next;
}
ns2.next = Some(ret);
} else {
elem.ns_def = Some(ret);
}
return Some(ret);
}
}
counter += 1;
if counter > 1000 {
return None;
}
let buf = if let Some(prefix) = prefix {
format!("{prefix}_{counter}")
} else {
format!("ns_{counter}")
};
pref = Some(buf);
}
}
#[allow(clippy::too_many_arguments)]
#[doc(alias = "xmlDOMWrapNSNormAcquireNormalizedNs")]
unsafe fn xml_dom_wrap_ns_norm_acquire_normalized_ns(
mut doc: XmlDocPtr,
elem: Option<XmlNodePtr>,
ns: XmlNsPtr,
ret_ns: &mut Option<XmlNsPtr>,
ns_map: *mut XmlNsMapPtr,
depth: i32,
ancestors_only: i32,
prefixed: i32,
) -> i32 {
unsafe {
let mut mi: XmlNsMapItemPtr;
if ns_map.is_null() {
return -1;
}
*ret_ns = None;
if ns.prefix().as_deref() == Some("xml") {
*ret_ns = doc.ensure_xmldecl();
if (*ret_ns).is_none() {
return -1;
}
return 0;
}
if XML_NSMAP_NOTEMPTY!(*ns_map) && !(ancestors_only != 0 && elem.is_none()) {
XML_NSMAP_FOREACH!(*ns_map, mi, {
if ((*mi).depth >= XML_TREE_NSMAP_PARENT)
&& (ancestors_only == 0 || (*mi).depth == XML_TREE_NSMAP_PARENT)
&& (*mi).shadow_depth == -1
&& (*mi)
.new_ns
.unwrap()
.href
.as_deref()
.is_some_and(|href| !href.is_empty())
&& (prefixed == 0 || (*mi).new_ns.unwrap().prefix().is_some())
&& (*mi).new_ns.unwrap().href == ns.href
{
(*mi).old_ns = Some(ns);
*ret_ns = (*mi).new_ns;
return 0;
}
});
}
if let Some(elem) = elem {
let Some(tmpns) = xml_dom_wrap_nsnorm_declare_ns_forced(
doc,
elem,
ns.href.as_deref(),
ns.prefix.as_deref(),
0,
) else {
return -1;
};
if !(*ns_map).is_null() {
XML_NSMAP_FOREACH!(*ns_map, mi, {
if ((*mi).depth < depth)
&& (*mi).shadow_depth == -1
&& ns.prefix() == (*mi).new_ns.unwrap().prefix()
{
(*mi).shadow_depth = depth;
break;
}
});
}
if xml_dom_wrap_ns_map_add_item(ns_map, -1, Some(ns), Some(tmpns), depth).is_null() {
xml_free_ns(tmpns);
return -1;
}
*ret_ns = Some(tmpns);
} else {
let Some(tmpns) =
xml_dom_wrap_store_ns(doc, ns.href.as_deref(), ns.prefix().as_deref())
else {
return -1;
};
if xml_dom_wrap_ns_map_add_item(ns_map, -1, Some(ns), Some(tmpns), XML_TREE_NSMAP_DOC)
.is_null()
{
xml_free_ns(tmpns);
return -1;
}
*ret_ns = Some(tmpns);
}
0
}
}
#[doc(alias = "xmlDOMWrapReconcileNamespaces")]
pub unsafe fn xml_dom_wrap_reconcile_namespaces(
_ctxt: XmlDOMWrapCtxtPtr,
elem: XmlNodePtr,
options: i32,
) -> i32 {
unsafe {
let mut depth: i32 = -1;
let mut adoptns: i32;
let mut parnsdone: i32 = 0;
let mut ns_map: XmlNsMapPtr = null_mut();
let mut mi: XmlNsMapItemPtr;
let ancestors_only: i32 = 0;
let opt_remove_redundant_ns: i32 =
if options & XmlDomreconcileNsoptions::XmlDomReconnsRemoveredund as i32 != 0 {
1
} else {
0
};
let mut list_redund = vec![];
let mut nb_redund: i32 = 0;
if !matches!(elem.element_type(), XmlElementType::XmlElementNode) {
return -1;
}
let Some(doc) = elem.doc else {
return -1;
};
let ret;
let mut cur = XmlGenericNodePtr::from(elem);
let mut cur_elem = None;
'exit: {
'internal_error: {
'main: loop {
match cur.element_type() {
XmlElementType::XmlElementNode => {
let mut cur_node = XmlNodePtr::try_from(cur).unwrap();
adoptns = 1;
cur_elem = Some(cur_node);
depth += 1;
if cur_node.ns_def.is_some() {
let mut prevns = None::<XmlNsPtr>;
let mut ns = cur_node.ns_def;
'b: while let Some(cur_ns) = ns {
if parnsdone == 0 {
if let Some(parent) = elem.parent().filter(|&p| {
Some(p) != p.document().map(|doc| doc.into())
}) {
if xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
Some(parent),
) == -1
{
break 'internal_error;
}
}
parnsdone = 1;
}
if opt_remove_redundant_ns != 0 && XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).depth >= XML_TREE_NSMAP_PARENT
&& (*mi).shadow_depth == -1
&& cur_ns.prefix() == (*mi).new_ns.unwrap().prefix()
&& cur_ns.href() == (*mi).new_ns.unwrap().href()
{
if xml_dom_wrap_ns_norm_add_ns_map_item2(
&mut list_redund,
&raw mut nb_redund,
cur_ns,
(*mi).new_ns.unwrap(),
) == -1
{
break 'internal_error;
}
if let Some(mut prevns) = prevns {
prevns.next = cur_ns.next;
} else {
cur_node.ns_def = cur_ns.next;
}
ns = cur_ns.next;
continue 'b;
}
});
}
if cur_node.ns.is_some()
&& adoptns != 0
&& cur_node.ns == Some(cur_ns)
{
adoptns = 0;
}
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).depth >= XML_TREE_NSMAP_PARENT
&& (*mi).shadow_depth == -1
&& cur_ns.prefix() == (*mi).new_ns.unwrap().prefix()
{
(*mi).shadow_depth = depth;
}
});
}
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
Some(cur_ns),
Some(cur_ns),
depth,
)
.is_null()
{
break 'internal_error;
}
prevns = Some(cur_ns);
ns = cur_ns.next;
}
}
if adoptns == 0 {
if matches!(cur_node.element_type(), XmlElementType::XmlElementNode)
{
if let Some(prop) = cur_node.properties {
cur = prop.into();
continue 'main;
}
}
}
if cur_node.ns.is_none() {
if matches!(cur_node.element_type(), XmlElementType::XmlElementNode)
{
if let Some(prop) = cur_node.properties {
cur = prop.into();
continue 'main;
}
}
}
if parnsdone == 0 {
if (*elem)
.parent()
.filter(|&p| {
Some(p) != p.document().map(|doc| doc.into())
&& xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
Some(p),
) == -1
})
.is_some()
{
break 'internal_error;
}
parnsdone = 1;
}
for (_, j) in (0..nb_redund).zip((0..).step_by(2)) {
if cur_node.ns == Some(list_redund[j]) {
cur_node.ns = Some(list_redund[j + 1]);
break;
}
}
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth == -1 && cur_node.ns == (*mi).old_ns {
cur_node.ns = (*mi).new_ns;
if matches!(
cur.element_type(),
XmlElementType::XmlElementNode
) {
if let Some(prop) = cur_node.properties {
cur = prop.into();
continue 'main;
}
}
}
});
}
let mut ns = None;
if xml_dom_wrap_ns_norm_acquire_normalized_ns(
doc,
cur_elem,
cur_node.ns.unwrap(),
&mut ns,
&raw mut ns_map,
depth,
ancestors_only,
matches!(cur.element_type(), XmlElementType::XmlAttributeNode)
as i32,
) == -1
{
break 'internal_error;
}
cur_node.ns = ns;
if matches!(cur.element_type(), XmlElementType::XmlElementNode) {
if let Some(prop) = cur_node.properties {
cur = prop.into();
continue 'main;
}
}
}
XmlElementType::XmlAttributeNode => {
let mut cur_attr = XmlAttrPtr::try_from(cur).unwrap();
if parnsdone == 0 {
if elem
.parent()
.filter(|&p| {
Some(p) != p.document().map(|doc| doc.into())
&& xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
Some(p),
) == -1
})
.is_some()
{
break 'internal_error;
}
parnsdone = 1;
}
for (_, j) in (0..nb_redund).zip((0..).step_by(2)) {
if cur_attr.ns == Some(list_redund[j]) {
cur_attr.ns = Some(list_redund[j + 1]);
break;
}
}
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth == -1 && cur_attr.ns == (*mi).old_ns {
cur_attr.ns = (*mi).new_ns;
}
});
}
let mut ns = None;
if xml_dom_wrap_ns_norm_acquire_normalized_ns(
doc,
cur_elem,
cur_attr.ns.unwrap(),
&mut ns,
&raw mut ns_map,
depth,
ancestors_only,
matches!(cur.element_type(), XmlElementType::XmlAttributeNode)
as i32,
) == -1
{
break 'internal_error;
}
cur_attr.ns = ns;
}
_ => {
'next_sibling: loop {
if cur == XmlGenericNodePtr::from(elem) {
break 'main;
}
if matches!(cur.element_type(), XmlElementType::XmlElementNode) {
if XML_NSMAP_NOTEMPTY!(ns_map) {
while !(*ns_map).last.is_null()
&& (*(*ns_map).last).depth >= depth
{
XML_NSMAP_POP!(ns_map, mi);
}
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth >= depth {
(*mi).shadow_depth = -1;
}
});
}
depth -= 1;
}
if let Some(next) = cur.next() {
cur = next;
} else {
if matches!(
cur.element_type(),
XmlElementType::XmlAttributeNode
) {
cur = cur.parent().unwrap();
break 'next_sibling;
}
cur = cur.parent().unwrap();
continue 'next_sibling;
}
continue 'main;
}
}
}
'into_content: loop {
if let Some(children) = cur.children().filter(|_| {
matches!(cur.element_type(), XmlElementType::XmlElementNode)
}) {
cur = children;
continue;
}
'next_sibling: loop {
if cur == XmlGenericNodePtr::from(elem) {
break 'main;
}
if matches!(cur.element_type(), XmlElementType::XmlElementNode) {
if XML_NSMAP_NOTEMPTY!(ns_map) {
while !(*ns_map).last.is_null()
&& (*(*ns_map).last).depth >= depth
{
XML_NSMAP_POP!(ns_map, mi);
}
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth >= depth {
(*mi).shadow_depth = -1;
}
});
}
depth -= 1;
}
if let Some(next) = cur.next() {
cur = next;
} else {
if matches!(cur.element_type(), XmlElementType::XmlAttributeNode) {
cur = cur.parent().unwrap();
continue 'into_content;
}
cur = cur.parent().unwrap();
continue 'next_sibling;
}
break 'next_sibling;
}
break 'into_content;
}
}
ret = 0;
break 'exit;
}
ret = -1;
}
for (_, j) in (0..nb_redund).zip((0..).step_by(2)) {
xml_free_ns(list_redund[j]);
}
if !ns_map.is_null() {
xml_dom_wrap_ns_map_free(ns_map);
}
ret
}
}
#[doc(alias = "xmlDOMWrapAdoptBranch")]
unsafe fn xml_dom_wrap_adopt_branch(
ctxt: XmlDOMWrapCtxtPtr,
source_doc: Option<XmlDocPtr>,
node: XmlNodePtr,
dest_doc: XmlDocPtr,
dest_parent: Option<XmlNodePtr>,
_options: i32,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let mut cur_elem = None;
let mut ns_map: XmlNsMapPtr = null_mut();
let mut mi: XmlNsMapItemPtr;
let mut depth: i32 = -1;
let mut parnsdone: i32;
let ancestors_only: i32 = 0;
if !ctxt.is_null() {
ns_map = (*ctxt).namespace_map as _;
}
if dest_parent.is_none() || (!ctxt.is_null() && (*ctxt).get_ns_for_node_func.is_some()) {
parnsdone = 1;
} else {
parnsdone = 0;
}
'exit: {
'internal_error: {
let mut cur = Some(XmlGenericNodePtr::from(node));
'main: while let Some(mut cur_node) = cur {
let mut leave_node = false;
if cur_node.document() != source_doc {
if cur_node.next().is_some() {
let mut next = cur_node.next();
while let Some(now) = next.filter(|now| {
!matches!(now.element_type(), XmlElementType::XmlXIncludeEnd)
&& now.document() != node.doc
}) {
cur_node = now;
next = now.next();
}
if cur_node.document() != node.doc {
leave_node = true;
}
} else {
leave_node = true;
}
}
if !leave_node {
cur_node.set_document(Some(dest_doc));
match cur_node.element_type() {
XmlElementType::XmlXIncludeStart | XmlElementType::XmlXIncludeEnd => {
return -1;
}
XmlElementType::XmlElementNode => {
let mut node = XmlNodePtr::try_from(cur_node).unwrap();
cur_elem = Some(node);
depth += 1;
if node.ns_def.is_some()
&& (ctxt.is_null() || (*ctxt).get_ns_for_node_func.is_none())
{
if parnsdone == 0 {
if xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
dest_parent.map(|d| d.into()),
) == -1
{
break 'internal_error;
}
parnsdone = 1;
}
let mut ns = node.ns_def;
while let Some(now) = ns {
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).depth >= XML_TREE_NSMAP_PARENT
&& (*mi).shadow_depth == -1
&& now.prefix()
== (*mi).new_ns.unwrap().prefix()
{
(*mi).shadow_depth = depth;
}
});
}
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
Some(now),
Some(now),
depth,
)
.is_null()
{
break 'internal_error;
}
ns = now.next;
}
}
if node.ns.is_some() {
if parnsdone == 0 {
if xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
dest_parent.map(|d| d.into()),
) == -1
{
break 'internal_error;
}
parnsdone = 1;
}
let mut ns_end = false;
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth == -1 && node.ns == (*mi).old_ns {
node.ns = (*mi).new_ns;
ns_end = true;
break;
}
});
}
if !ns_end {
if !ctxt.is_null() && (*ctxt).get_ns_for_node_func.is_some()
{
let ns = ((*ctxt).get_ns_for_node_func.unwrap())(
ctxt,
Some(node.into()),
node.ns.unwrap().href.as_deref(),
node.ns.unwrap().prefix.as_deref(),
);
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
node.ns,
ns,
XML_TREE_NSMAP_CUSTOM,
)
.is_null()
{
break 'internal_error;
}
node.ns = ns;
} else {
let mut ns = None;
if xml_dom_wrap_ns_norm_acquire_normalized_ns(
dest_doc,
dest_parent.and(cur_elem),
node.ns.unwrap(),
&mut ns,
&raw mut ns_map,
depth,
ancestors_only,
matches!(
node.element_type(),
XmlElementType::XmlAttributeNode
)
as i32,
) == -1
{
break 'internal_error;
}
node.ns = ns;
}
}
}
node.psvi = null_mut();
node.line = 0;
node.extra = 0;
if let Some(prop) = node.properties {
cur = Some(prop.into());
continue;
}
}
XmlElementType::XmlAttributeNode => {
let mut attr = XmlAttrPtr::try_from(cur_node).unwrap();
if attr.ns.is_some() {
if parnsdone == 0 {
if xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
dest_parent.map(|d| d.into()),
) == -1
{
break 'internal_error;
}
parnsdone = 1;
}
let mut ns_end = false;
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth == -1 && attr.ns == (*mi).old_ns {
attr.ns = (*mi).new_ns;
ns_end = true;
break;
}
});
}
if !ns_end {
if !ctxt.is_null() && (*ctxt).get_ns_for_node_func.is_some()
{
let ns = ((*ctxt).get_ns_for_node_func.unwrap())(
ctxt,
Some(attr.into()),
attr.ns.unwrap().href.as_deref(),
attr.ns.unwrap().prefix.as_deref(),
);
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
attr.ns,
ns,
XML_TREE_NSMAP_CUSTOM,
)
.is_null()
{
break 'internal_error;
}
attr.ns = ns;
} else {
let mut ns = None;
if xml_dom_wrap_ns_norm_acquire_normalized_ns(
dest_doc,
dest_parent.and(cur_elem),
attr.ns.unwrap(),
&mut ns,
&raw mut ns_map,
depth,
ancestors_only,
matches!(
attr.element_type(),
XmlElementType::XmlAttributeNode
)
as i32,
) == -1
{
break 'internal_error;
}
attr.ns = ns;
}
}
}
if let Some(source_doc) = source_doc.filter(|_| {
matches!(attr.atype, Some(XmlAttributeType::XmlAttributeID))
}) {
xml_remove_id(source_doc, attr);
}
attr.atype = None;
attr.psvi = null_mut();
}
XmlElementType::XmlTextNode | XmlElementType::XmlCDATASectionNode => {
leave_node = true;
}
XmlElementType::XmlEntityRefNode => {
let mut cur = XmlNodePtr::try_from(cur_node).unwrap();
cur.content = None;
cur.set_children(None);
cur.set_last(None);
if dest_doc.int_subset.is_some() || dest_doc.ext_subset.is_some() {
let ent =
xml_get_doc_entity(Some(dest_doc), &cur.name().unwrap());
if let Some(ent) = ent {
cur.content =
ent.content.as_deref().map(|cont| cont.to_owned());
cur.set_children(Some(ent.into()));
cur.set_last(Some(ent.into()));
}
}
leave_node = true;
}
XmlElementType::XmlPINode => {}
XmlElementType::XmlCommentNode => {}
_ => {
break 'internal_error;
}
}
if !leave_node {
if let Some(children) = cur_node.children() {
cur = Some(children);
continue;
}
}
}
'leave_node: loop {
if cur_node == XmlGenericNodePtr::from(node) {
break 'main;
}
if matches!(
cur_node.element_type(),
XmlElementType::XmlElementNode
| XmlElementType::XmlXIncludeStart
| XmlElementType::XmlXIncludeEnd
) {
if XML_NSMAP_NOTEMPTY!(ns_map) {
while !(*ns_map).last.is_null() && (*(*ns_map).last).depth >= depth
{
XML_NSMAP_POP!(ns_map, mi);
}
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth >= depth {
(*mi).shadow_depth = -1;
}
});
}
depth -= 1;
}
if let Some(next) = cur_node.next() {
cur_node = next;
} else if let Some(children) = cur_node.parent().and_then(|p| {
p.children().filter(|_| {
matches!(cur_node.element_type(), XmlElementType::XmlAttributeNode)
})
}) {
cur_node = children;
} else {
cur_node = cur_node.parent().unwrap();
continue 'leave_node;
}
cur = Some(cur_node);
break;
}
}
break 'exit;
}
ret = -1;
}
if !ns_map.is_null() {
if !ctxt.is_null() && (*ctxt).namespace_map == ns_map as _ {
if !(*ns_map).first.is_null() {
if !(*ns_map).pool.is_null() {
(*(*ns_map).last).next = (*ns_map).pool;
}
(*ns_map).pool = (*ns_map).first;
(*ns_map).first = null_mut();
}
} else {
xml_dom_wrap_ns_map_free(ns_map);
}
}
ret
}
}
#[doc(alias = "xmlDOMWrapAdoptAttr")]
fn xml_dom_wrap_adopt_attr(
ctxt: XmlDOMWrapCtxtPtr,
_source_doc: Option<XmlDocPtr>,
mut attr: XmlAttrPtr,
mut dest_doc: XmlDocPtr,
dest_parent: Option<XmlNodePtr>,
_options: i32,
) -> i32 {
attr.doc = Some(dest_doc);
if let Some(attr_ns) = attr.ns {
let mut ns = None;
if !ctxt.is_null() { }
if attr_ns.prefix().as_deref() == Some("xml") {
ns = dest_doc.ensure_xmldecl();
} else if let Some(dest_parent) = dest_parent {
if xml_search_ns_by_namespace_strict(
dest_doc,
dest_parent.into(),
attr_ns.href.as_deref().unwrap(),
&mut ns,
1,
) == -1
{
return -1;
}
if ns.is_none() {
ns = xml_dom_wrap_nsnorm_declare_ns_forced(
dest_doc,
dest_parent,
attr_ns.href.as_deref(),
attr_ns.prefix.as_deref(),
1,
);
}
} else {
ns = xml_dom_wrap_store_ns(
dest_doc,
attr_ns.href.as_deref(),
attr_ns.prefix().as_deref(),
);
}
let Some(ns) = ns else {
return -1;
};
attr.ns = Some(ns);
}
attr.atype = None;
attr.psvi = null_mut();
let Some(children) = attr.children() else {
return 0;
};
if matches!(children.element_type(), XmlElementType::XmlNamespaceDecl) {
return -1;
}
let mut cur = Some(children);
'main: while let Some(mut cur_node) = cur {
cur_node.set_document(Some(dest_doc));
match cur_node.element_type() {
XmlElementType::XmlTextNode | XmlElementType::XmlCDATASectionNode => {}
XmlElementType::XmlEntityRefNode => {
let mut cur = XmlNodePtr::try_from(cur_node).unwrap();
cur.content = None;
cur.set_children(None);
cur.set_last(None);
if dest_doc.int_subset.is_some() || dest_doc.ext_subset.is_some() {
let ent = xml_get_doc_entity(Some(dest_doc), &cur.name().unwrap());
if let Some(ent) = ent {
cur.content = ent.content.as_deref().map(|cont| cont.to_owned());
cur.set_children(Some(ent.into()));
cur.set_last(Some(ent.into()));
}
}
}
_ => {}
}
if let Some(children) = cur_node.children() {
cur = Some(children);
continue;
}
'next_sibling: loop {
if cur_node == XmlGenericNodePtr::from(attr) {
break 'main;
}
if let Some(next) = cur_node.next() {
cur_node = next;
} else {
cur_node = cur_node.parent().unwrap();
continue 'next_sibling;
}
cur = Some(cur_node);
break 'next_sibling;
}
}
0
}
#[doc(alias = "xmlDOMWrapAdoptNode")]
pub unsafe fn xml_dom_wrap_adopt_node(
ctxt: XmlDOMWrapCtxtPtr,
source_doc: Option<XmlDocPtr>,
mut node: XmlGenericNodePtr,
dest_doc: XmlDocPtr,
dest_parent: Option<XmlNodePtr>,
options: i32,
) -> i32 {
unsafe {
if matches!(node.element_type(), XmlElementType::XmlNamespaceDecl)
|| dest_parent.is_some_and(|dest_parent| dest_parent.doc != Some(dest_doc))
{
return -1;
}
if node.document().is_some_and(|doc| Some(doc) != source_doc) && source_doc.is_some() {
return -1;
}
let source_doc = source_doc.or(node.document());
if source_doc == Some(dest_doc) {
return -1;
}
match node.element_type() {
XmlElementType::XmlElementNode
| XmlElementType::XmlAttributeNode
| XmlElementType::XmlTextNode
| XmlElementType::XmlCDATASectionNode
| XmlElementType::XmlEntityRefNode
| XmlElementType::XmlPINode
| XmlElementType::XmlCommentNode => {}
XmlElementType::XmlDocumentFragNode => {
return 2;
}
_ => {
return 1;
}
}
if node
.parent()
.filter(|&p| Some(p) != dest_parent.map(|d| d.into()))
.is_some()
{
node.unlink();
}
if let Some(node) = XmlNodePtr::try_from(node)
.ok()
.filter(|node| matches!(node.element_type(), XmlElementType::XmlElementNode))
{
return xml_dom_wrap_adopt_branch(
ctxt,
source_doc,
node,
dest_doc,
dest_parent,
options,
);
} else if let Ok(attr) = XmlAttrPtr::try_from(node) {
return xml_dom_wrap_adopt_attr(ctxt, source_doc, attr, dest_doc, dest_parent, options);
} else {
node.set_document(Some(dest_doc));
match node.element_type() {
XmlElementType::XmlTextNode | XmlElementType::XmlCDATASectionNode => {}
XmlElementType::XmlEntityRefNode => {
let mut node = XmlNodePtr::try_from(node).unwrap();
node.content = None;
node.set_children(None);
node.set_last(None);
if dest_doc.int_subset.is_some() || dest_doc.ext_subset.is_some() {
let ent = xml_get_doc_entity(Some(dest_doc), &node.name().unwrap());
if let Some(ent) = ent {
node.content = ent.content.as_deref().map(|cont| cont.to_owned());
node.set_children(Some(ent.into()));
node.set_last(Some(ent.into()));
}
}
}
XmlElementType::XmlPINode => {}
_ => {}
}
}
0
}
}
#[doc(alias = "xmlDOMWrapRemoveNode")]
pub unsafe fn xml_dom_wrap_remove_node(
ctxt: XmlDOMWrapCtxtPtr,
doc: XmlDocPtr,
mut node: XmlGenericNodePtr,
_options: i32,
) -> i32 {
unsafe {
let mut list = vec![];
let mut nb_list: i32 = 0;
if node.document() != Some(doc) {
return -1;
}
if node.parent().is_none() {
return 0;
}
match node.element_type() {
XmlElementType::XmlTextNode
| XmlElementType::XmlCDATASectionNode
| XmlElementType::XmlEntityRefNode
| XmlElementType::XmlPINode
| XmlElementType::XmlCommentNode => {
node.unlink();
return 0;
}
XmlElementType::XmlElementNode | XmlElementType::XmlAttributeNode => {}
_ => {
return 1;
}
}
node.unlink();
'main: loop {
match node.element_type() {
XmlElementType::XmlElementNode => {
let mut cur_node = XmlNodePtr::try_from(node).unwrap();
if ctxt.is_null() && cur_node.ns_def.is_some() {
let mut ns = cur_node.ns_def;
while let Some(now) = ns {
if xml_dom_wrap_ns_norm_add_ns_map_item2(
&mut list,
&raw mut nb_list,
now,
now,
) == -1
{
return -1;
}
ns = now.next;
}
}
if cur_node.ns.is_some() {
for (_, j) in (0..nb_list).zip((0..).step_by(2)) {
if cur_node.ns == Some(list[j]) {
cur_node.ns = Some(list[j + 1]);
if let Some(children) = cur_node.children().filter(|_| {
matches!(
cur_node.element_type(),
XmlElementType::XmlElementNode
)
}) {
node = children;
continue 'main;
}
'next_sibling: loop {
if let Some(next) = node.next() {
node = next;
} else {
let Some(parent) = node.parent() else {
break 'main;
};
node = parent;
continue 'next_sibling;
}
continue 'main;
}
}
}
let mut ns = None;
if !ctxt.is_null() {
} else {
ns = xml_dom_wrap_store_ns(
doc,
cur_node.ns.unwrap().href.as_deref(),
cur_node.ns.unwrap().prefix().as_deref(),
);
if ns.is_none() {
return -1;
}
}
if let Some(ns) = ns {
if xml_dom_wrap_ns_norm_add_ns_map_item2(
&mut list,
&raw mut nb_list,
cur_node.ns.unwrap(),
ns,
) == -1
{
return -1;
}
}
cur_node.ns = ns;
}
if matches!(node.element_type(), XmlElementType::XmlElementNode) {
if let Some(prop) = cur_node.properties {
node = XmlGenericNodePtr::from(prop);
continue;
}
}
}
XmlElementType::XmlAttributeNode => {
let mut attr = XmlAttrPtr::try_from(node).unwrap();
if attr.ns.is_some() {
for (_, j) in (0..nb_list).zip((0..).step_by(2)) {
if attr.ns == Some(list[j]) {
attr.ns = Some(list[j + 1]);
if let Some(children) = attr.children().filter(|_| {
matches!(attr.element_type(), XmlElementType::XmlElementNode)
}) {
node = children;
continue 'main;
}
'next_sibling: loop {
if let Some(next) = node.next() {
node = next;
} else {
let Some(parent) = node.parent() else {
break 'main;
};
node = parent;
continue 'next_sibling;
}
continue 'main;
}
}
}
let mut ns = None;
if !ctxt.is_null() {
} else {
ns = xml_dom_wrap_store_ns(
doc,
attr.ns.unwrap().href.as_deref(),
attr.ns.unwrap().prefix().as_deref(),
);
if ns.is_none() {
return -1;
}
}
if let Some(ns) = ns {
if xml_dom_wrap_ns_norm_add_ns_map_item2(
&mut list,
&raw mut nb_list,
attr.ns.unwrap(),
ns,
) == -1
{
return -1;
}
}
attr.ns = ns;
}
}
_ => {
'next_sibling: loop {
if let Some(next) = node.next() {
node = next;
} else {
let Some(parent) = node.parent() else {
break 'main;
};
node = parent;
continue 'next_sibling;
}
continue 'main;
}
}
}
if let Some(children) = node
.children()
.filter(|_| matches!(node.element_type(), XmlElementType::XmlElementNode))
{
node = children;
continue;
}
'next_sibling: loop {
if let Some(next) = node.next() {
node = next;
} else {
let Some(parent) = node.parent() else {
break 'main;
};
node = parent;
continue 'next_sibling;
}
continue 'main;
}
}
0
}
}
#[doc(alias = "xmlDOMWrapCloneNode")]
#[allow(clippy::too_many_arguments)]
pub unsafe fn xml_dom_wrap_clone_node(
ctxt: XmlDOMWrapCtxtPtr,
source_doc: Option<XmlDocPtr>,
node: XmlGenericNodePtr,
res_node: &mut Option<XmlGenericNodePtr>,
dest_doc: XmlDocPtr,
dest_parent: Option<XmlGenericNodePtr>,
deep: i32,
_options: i32,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let mut cur_elem = None;
let mut ns_map: XmlNsMapPtr = null_mut();
let mut mi: XmlNsMapItemPtr;
let mut depth: i32 = -1;
let mut parnsdone: i32 = 0;
let ancestors_only: i32 = 0;
let mut result_clone: Option<XmlGenericNodePtr> = None;
let mut parent_clone: Option<XmlGenericNodePtr> = None;
let mut prev_clone: Option<XmlGenericNodePtr> = None;
if !matches!(node.element_type(), XmlElementType::XmlElementNode) {
return 1;
}
if node.document().is_some_and(|doc| Some(doc) != source_doc) && source_doc.is_some() {
return -1;
}
let Some(source_doc) = source_doc.or(node.document()) else {
return -1;
};
if !ctxt.is_null() {
ns_map = (*ctxt).namespace_map as _;
}
*res_node = None;
let mut cur = Some(node);
'exit: {
'internal_error: {
'main: while let Some(cur_node) = cur {
if cur_node.document() != Some(source_doc) {
break 'internal_error;
}
let mut clone = match cur_node.element_type() {
XmlElementType::XmlXIncludeStart | XmlElementType::XmlXIncludeEnd => {
break 'internal_error;
}
XmlElementType::XmlElementNode
| XmlElementType::XmlTextNode
| XmlElementType::XmlCDATASectionNode
| XmlElementType::XmlCommentNode
| XmlElementType::XmlPINode
| XmlElementType::XmlDocumentFragNode
| XmlElementType::XmlEntityRefNode
| XmlElementType::XmlEntityNode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
let Some(mut new) = XmlNodePtr::new(XmlNode::default()) else {
xml_tree_err_memory("xmlDOMWrapCloneNode(): allocating a node");
break 'internal_error;
};
new.typ = cur_node.element_type();
if result_clone.is_some() {
new.set_parent(parent_clone);
if let Some(mut prev_clone) = prev_clone {
prev_clone.set_next(Some(new.into()));
new.set_prev(Some(prev_clone));
} else {
parent_clone.unwrap().set_children(Some(new.into()));
}
} else {
result_clone = Some(XmlGenericNodePtr::from(new));
}
new.name = cur_node.name.clone();
XmlGenericNodePtr::from(new)
}
XmlElementType::XmlAttributeNode => {
let cur_node = XmlAttrPtr::try_from(cur_node).unwrap();
let Some(mut new) = XmlAttrPtr::new(XmlAttr::default()) else {
xml_tree_err_memory(
"xmlDOMWrapCloneNode(): allocating an attr-node",
);
break 'internal_error;
};
new.typ = cur_node.element_type();
if result_clone.is_some() {
new.set_parent(parent_clone);
if let Some(mut prev_clone) = prev_clone {
prev_clone.set_next(Some(new.into()));
new.prev = XmlAttrPtr::try_from(prev_clone).ok();
} else {
XmlNodePtr::try_from(parent_clone.unwrap())
.unwrap()
.properties = Some(new);
}
} else {
result_clone = Some(new.into());
}
new.name = cur_node.name.clone();
XmlGenericNodePtr::from(new)
}
_ => {
break 'internal_error;
}
};
clone.set_document(Some(dest_doc));
let mut leave_node = false;
match cur_node.element_type() {
XmlElementType::XmlXIncludeStart | XmlElementType::XmlXIncludeEnd => {
return -1;
}
XmlElementType::XmlElementNode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
cur_elem = Some(cur_node);
depth += 1;
if cur_node.ns_def.is_some() {
if parnsdone == 0 {
if dest_parent.is_some() && ctxt.is_null() {
if xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
dest_parent,
) == -1
{
break 'internal_error;
}
}
parnsdone = 1;
}
let mut clone_ns_def_slot = None::<XmlNsPtr>;
let mut ns = cur_node.ns_def;
while let Some(now) = ns {
let Some(mut new) = XmlNsPtr::new(XmlNs {
typ: XML_LOCAL_NAMESPACE,
..Default::default()
}) else {
xml_tree_err_memory(
"xmlDOMWrapCloneNode(): allocating namespace",
);
return -1;
};
new.href = now.href.clone();
new.prefix = now.prefix.clone();
if let Some(mut last) = clone_ns_def_slot {
last.next = Some(new);
clone_ns_def_slot = Some(new);
} else {
clone_ns_def_slot = Some(new);
XmlNodePtr::try_from(clone).unwrap().ns_def = Some(new);
}
if ctxt.is_null() || (*ctxt).get_ns_for_node_func.is_none() {
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if ((*mi).depth >= XML_TREE_NSMAP_PARENT)
&& (*mi).shadow_depth == -1
&& now.prefix()
== (*mi).new_ns.unwrap().prefix()
{
(*mi).shadow_depth = depth;
}
});
}
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
Some(now),
Some(new),
depth,
)
.is_null()
{
break 'internal_error;
}
}
ns = now.next;
}
}
}
XmlElementType::XmlAttributeNode => {
}
XmlElementType::XmlTextNode | XmlElementType::XmlCDATASectionNode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
XmlNodePtr::try_from(clone).unwrap().content = cur_node.content.clone();
leave_node = true;
}
XmlElementType::XmlEntityNode => {
leave_node = true;
}
XmlElementType::XmlEntityRefNode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
if source_doc != dest_doc {
if dest_doc.int_subset.is_some() || dest_doc.ext_subset.is_some() {
let ent = xml_get_doc_entity(
Some(dest_doc),
&cur_node.name().unwrap(),
);
if let Some(ent) = ent {
XmlNodePtr::try_from(clone).unwrap().content =
ent.content.as_deref().map(|cont| cont.to_owned());
clone.set_children(Some(ent.into()));
clone.set_last(Some(ent.into()));
}
}
} else {
XmlNodePtr::try_from(clone).unwrap().content =
cur_node.content.clone();
clone.set_children(cur_node.children());
clone.set_last(cur_node.last());
}
leave_node = true;
}
XmlElementType::XmlPINode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
XmlNodePtr::try_from(clone).unwrap().content = cur_node.content.clone();
leave_node = true;
}
XmlElementType::XmlCommentNode => {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
XmlNodePtr::try_from(clone).unwrap().content = cur_node.content.clone();
leave_node = true;
}
_ => {
break 'internal_error;
}
}
if !leave_node {
let cur_ns = if let Ok(node) = XmlNodePtr::try_from(node) {
node.ns
} else {
XmlAttrPtr::try_from(node).unwrap().ns
};
if let Some(cur_ns) = cur_ns {
if parnsdone == 0 {
if dest_parent.is_some()
&& ctxt.is_null()
&& xml_dom_wrap_ns_norm_gather_in_scope_ns(
&raw mut ns_map,
dest_parent,
) == -1
{
break 'internal_error;
}
parnsdone = 1;
}
let mut end_ns_reference = false;
if XML_NSMAP_NOTEMPTY!(ns_map) {
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth == -1 && Some(cur_ns) == (*mi).old_ns {
XmlNodePtr::try_from(clone).unwrap().ns = (*mi).new_ns;
end_ns_reference = true;
break;
}
});
}
if !end_ns_reference {
if !ctxt.is_null() && (*ctxt).get_ns_for_node_func.is_some() {
let ns = ((*ctxt).get_ns_for_node_func.unwrap())(
ctxt,
Some(cur_node),
cur_ns.href.as_deref(),
cur_ns.prefix.as_deref(),
);
if xml_dom_wrap_ns_map_add_item(
&raw mut ns_map,
-1,
Some(cur_ns),
ns,
XML_TREE_NSMAP_CUSTOM,
)
.is_null()
{
break 'internal_error;
}
XmlNodePtr::try_from(clone).unwrap().ns = ns;
} else {
let mut ns = None;
if xml_dom_wrap_ns_norm_acquire_normalized_ns(
dest_doc,
dest_parent.and(cur_elem),
cur_ns,
&mut ns,
&raw mut ns_map,
depth,
ancestors_only,
matches!(
cur_node.element_type(),
XmlElementType::XmlAttributeNode
) as i32,
) == -1
{
break 'internal_error;
}
XmlNodePtr::try_from(clone).unwrap().ns = ns;
}
}
}
if matches!(clone.element_type(), XmlElementType::XmlAttributeNode)
&& clone.parent().is_some()
&& xml_is_id(
Some(dest_doc),
Some(XmlNodePtr::try_from(clone.parent().unwrap()).unwrap()),
XmlAttrPtr::try_from(clone).ok(),
) != 0
{
let children = cur_node.children();
if let Some(id_val) =
children.and_then(|c| c.get_string(cur_node.document(), 1))
{
if xml_add_id(
None,
dest_doc,
&id_val,
XmlAttrPtr::try_from(cur_node).unwrap(),
)
.is_none()
{
break 'internal_error;
}
}
}
if matches!(cur_node.element_type(), XmlElementType::XmlElementNode) {
let cur_node = XmlNodePtr::try_from(cur_node).unwrap();
if let Some(prop) = cur_node.properties {
prev_clone = None;
parent_clone = Some(clone);
cur = Some(prop.into());
continue 'main;
}
}
if let Some(children) = cur_node.children().filter(|_| {
deep != 0
|| matches!(
cur_node.element_type(),
XmlElementType::XmlAttributeNode
)
}) {
prev_clone = None;
parent_clone = Some(clone);
cur = Some(children);
continue 'main;
}
}
'leave_node: loop {
if cur == Some(node) {
break 'main;
}
let cur_node = cur.unwrap();
if matches!(cur_node.element_type(), XmlElementType::XmlElementNode)
|| matches!(cur_node.element_type(), XmlElementType::XmlXIncludeStart)
|| matches!(cur_node.element_type(), XmlElementType::XmlXIncludeEnd)
{
if XML_NSMAP_NOTEMPTY!(ns_map) {
while !(*ns_map).last.is_null() && (*(*ns_map).last).depth >= depth
{
XML_NSMAP_POP!(ns_map, mi);
}
XML_NSMAP_FOREACH!(ns_map, mi, {
if (*mi).shadow_depth >= depth {
(*mi).shadow_depth = -1;
}
});
}
depth -= 1;
}
if let Some(next) = cur_node.next() {
prev_clone = Some(clone);
cur = Some(next);
} else if !matches!(
cur_node.element_type(),
XmlElementType::XmlAttributeNode
) {
if let Some(mut parent) = clone.parent() {
parent.set_last(Some(clone));
}
clone = clone.parent().unwrap();
parent_clone = clone.parent();
cur = cur_node.parent();
continue 'leave_node;
} else {
clone = clone.parent().unwrap();
parent_clone = clone.parent();
cur = cur_node.parent();
if let Some(children) = cur_node.children().filter(|_| {
deep != 0
|| matches!(
cur_node.element_type(),
XmlElementType::XmlAttributeNode
)
}) {
prev_clone = None;
parent_clone = Some(clone);
cur = Some(children);
continue 'main;
}
continue 'leave_node;
}
break;
}
}
break 'exit;
}
ret = -1;
}
if !ns_map.is_null() {
if !ctxt.is_null() && (*ctxt).namespace_map == ns_map as _ {
if !(*ns_map).first.is_null() {
if !(*ns_map).pool.is_null() {
(*(*ns_map).last).next = (*ns_map).pool;
}
(*ns_map).pool = (*ns_map).first;
(*ns_map).first = null_mut();
}
} else {
xml_dom_wrap_ns_map_free(ns_map);
}
}
*res_node = result_clone;
ret
}
}