1#![forbid(unsafe_code)]
5
6use std::collections::HashMap;
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10#[repr(u32)]
11pub enum NodeKind {
12 Element = 1,
13 Attribute = 2,
14 Text = 3,
15 CData = 4,
16 EntityRef = 5,
17 Entity = 6,
18 Pi = 7,
19 Comment = 8,
20 Document = 9,
21 DocumentType = 10,
22 DocumentFrag = 11,
23 Notation = 12,
24 HtmlDocument = 13,
25 Dtd = 14,
26 ElementDecl = 15,
27 AttributeDecl = 16,
28 EntityDecl = 17,
29 Namespace = 18,
30 XIncludeStart = 19,
31 XIncludeEnd = 20,
32}
33
34#[derive(Clone, Debug, Default)]
36pub struct XmlDtd {
37 pub name: Option<String>,
38 pub public_id: Option<String>,
39 pub system_id: Option<String>,
40 pub int_subset: Option<String>,
41 pub entities: HashMap<String, String>,
43 pub parameter_entities: HashMap<String, String>,
45 pub unparsed_entities: std::collections::HashSet<String>,
49 pub notations: std::collections::HashSet<String>,
53 pub ndata_notations: Vec<String>,
57 pub has_parameter_entity_refs: bool,
62 pub namespace_errors: Vec<String>,
65 pub elements: HashMap<String, ElementDecl>,
67 pub duplicate_elements: Vec<String>,
72 pub attributes: HashMap<(String, String), AttrDecl>,
74}
75
76#[derive(Clone, Debug)]
77pub enum ElementDecl {
78 Empty,
79 Any,
80 Mixed(Vec<String>),
81 Children(String),
82}
83
84#[derive(Clone, Debug)]
85pub struct AttrDecl {
86 pub att_type: String,
87 pub default: AttrDefault,
88 pub default_value: Option<String>,
89 pub enumerated: Vec<String>,
90}
91
92#[derive(Clone, Copy, Debug, PartialEq, Eq)]
93pub enum AttrDefault {
94 Required,
95 Implied,
96 Fixed,
97 Value,
98}
99
100#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
102pub struct NodeId(pub u32);
103
104impl NodeId {
105 pub const DOCUMENT: NodeId = NodeId(0);
107
108 pub fn index(self) -> usize {
109 self.0 as usize
110 }
111}
112
113
114
115#[derive(Clone, Debug)]
116pub struct Node {
117 pub kind: NodeKind,
118 pub name: String,
119 pub prefix: Option<String>,
120 pub ns_uri: Option<String>,
121 pub content: String,
122 pub parent: Option<NodeId>,
123 pub first_child: Option<NodeId>,
124 pub last_child: Option<NodeId>,
125 pub prev_sibling: Option<NodeId>,
126 pub next_sibling: Option<NodeId>,
127 pub first_attr: Option<NodeId>,
128 pub last_attr: Option<NodeId>,
129 pub ns_defs: Vec<(Option<String>, String)>,
131}
132
133impl Node {
134 fn new(kind: NodeKind, name: String) -> Self {
135 Self {
136 kind,
137 name,
138 prefix: None,
139 ns_uri: None,
140 content: String::new(),
141 parent: None,
142 first_child: None,
143 last_child: None,
144 prev_sibling: None,
145 next_sibling: None,
146 first_attr: None,
147 last_attr: None,
148 ns_defs: Vec::new(),
149 }
150 }
151}
152
153#[derive(Clone, Debug)]
155pub struct XmlDoc {
156 nodes: Vec<Node>,
157 pub version: String,
159 pub encoding: Option<String>,
161 pub standalone: Option<bool>,
163 root: Option<NodeId>,
165 pub dtd: Option<XmlDtd>,
167 pub undeclared_entity_refs: Vec<String>,
171 pub namespace_errors: Vec<String>,
185 pub warnings: Vec<String>,
190 pub reference_text: std::collections::HashSet<NodeId>,
191 pub elements_with_entity_refs: std::collections::HashSet<NodeId>,
195}
196
197impl Default for XmlDoc {
198 fn default() -> Self {
199 Self::xml_new_doc(Some("1.0"))
200 }
201}
202
203impl XmlDoc {
204 #[doc(alias = "xmlNewDoc")]
206 pub fn xml_new_doc(version: Option<&str>) -> Self {
207 Self::with_node_capacity(version, 1)
208 }
209
210 pub fn with_node_capacity(version: Option<&str>, cap: usize) -> Self {
215 const MAX_ARENA_BYTES: usize = 32 << 20;
216 let ceiling = MAX_ARENA_BYTES / std::mem::size_of::<Node>();
217 let mut nodes = Vec::with_capacity(cap.clamp(4, ceiling));
220 nodes.push(Node::new(NodeKind::Document, String::new()));
221 Self {
222 nodes,
223 version: version.unwrap_or("1.0").to_string(),
224 encoding: None,
225 standalone: None,
226 root: None,
227 dtd: None,
228 undeclared_entity_refs: Vec::new(),
229 namespace_errors: Vec::new(),
230 warnings: Vec::new(),
231 reference_text: Default::default(),
232 elements_with_entity_refs: Default::default(),
233 }
234 }
235
236 pub fn reserve_nodes(&mut self, n: usize) {
240 const MAX_ARENA_BYTES: usize = 32 << 20;
248 let cap = MAX_ARENA_BYTES / std::mem::size_of::<Node>();
249 self.nodes.reserve(n.min(cap));
250 }
251
252 pub fn node(&self, id: NodeId) -> &Node {
253 &self.nodes[id.index()]
254 }
255
256 pub fn node_mut(&mut self, id: NodeId) -> &mut Node {
257 &mut self.nodes[id.index()]
258 }
259
260 pub fn kind(&self, id: NodeId) -> NodeKind {
261 self.node(id).kind
262 }
263
264 pub fn name(&self, id: NodeId) -> &str {
265 let n = self.node(id);
266 if n.name.is_empty() {
267 return match n.kind {
271 NodeKind::Text => "#text",
272 NodeKind::CData => "#cdata-section",
273 NodeKind::Comment => "#comment",
274 NodeKind::Document => "#document",
275 _ => "",
276 };
277 }
278 &n.name
279 }
280
281 pub fn prefix(&self, id: NodeId) -> Option<&str> {
282 self.node(id).prefix.as_deref()
283 }
284
285 pub fn ns_uri(&self, id: NodeId) -> Option<&str> {
286 self.node(id).ns_uri.as_deref()
287 }
288
289 pub fn content(&self, id: NodeId) -> &str {
290 &self.node(id).content
291 }
292
293 pub fn parent(&self, id: NodeId) -> Option<NodeId> {
294 self.node(id).parent
295 }
296
297 pub fn first_child(&self, id: NodeId) -> Option<NodeId> {
298 self.node(id).first_child
299 }
300
301 pub fn last_child(&self, id: NodeId) -> Option<NodeId> {
302 self.node(id).last_child
303 }
304
305 pub fn next_sibling(&self, id: NodeId) -> Option<NodeId> {
306 self.node(id).next_sibling
307 }
308
309 pub fn prev_sibling(&self, id: NodeId) -> Option<NodeId> {
310 self.node(id).prev_sibling
311 }
312
313 pub fn first_attr(&self, id: NodeId) -> Option<NodeId> {
314 self.node(id).first_attr
315 }
316
317 pub fn ns_defs(&self, id: NodeId) -> &[(Option<String>, String)] {
318 &self.node(id).ns_defs
319 }
320
321 pub fn alloc_unnamed(&mut self, kind: NodeKind) -> NodeId {
324 let id = NodeId(self.nodes.len() as u32);
325 self.nodes.push(Node::new(kind, String::new()));
326 id
327 }
328
329 pub fn alloc(&mut self, kind: NodeKind, name: impl Into<String>) -> NodeId {
330 let id = NodeId(self.nodes.len() as u32);
331 self.nodes.push(Node::new(kind, name.into()));
332 id
333 }
334
335 #[doc(alias = "xmlDocGetRootElement")]
337 pub fn xml_doc_get_root_element(&self) -> Option<NodeId> {
338 if let Some(r) = self.root {
339 return Some(r);
340 }
341 let mut c = self.first_child(NodeId::DOCUMENT);
342 while let Some(id) = c {
343 if self.kind(id) == NodeKind::Element {
344 return Some(id);
345 }
346 c = self.next_sibling(id);
347 }
348 None
349 }
350
351 #[doc(alias = "xmlDocSetRootElement")]
353 pub fn xml_doc_set_root_element(&mut self, elem: NodeId) -> Option<NodeId> {
354 let prev = self.xml_doc_get_root_element();
355 if let Some(p) = prev {
356 self.xml_unlink_node(p);
357 }
358 self.xml_add_child(NodeId::DOCUMENT, elem);
359 self.root = Some(elem);
360 prev
361 }
362
363 #[doc(alias = "xmlNewNode")]
365 pub fn xml_new_node(&mut self, ns_uri: Option<&str>, name: &str) -> NodeId {
366 let id = self.alloc(NodeKind::Element, name);
367 self.node_mut(id).ns_uri = ns_uri.map(str::to_string);
368 id
369 }
370
371 #[doc(alias = "xmlNewDocNode")]
373 pub fn xml_new_doc_node(
374 &mut self,
375 ns_uri: Option<&str>,
376 name: &str,
377 content: Option<&str>,
378 ) -> NodeId {
379 let id = self.xml_new_node(ns_uri, name);
380 if let Some(c) = content {
381 if !c.is_empty() {
382 let t = self.alloc(NodeKind::Text, "#text");
383 self.node_mut(t).content = c.to_string();
384 self.xml_add_child(id, t);
385 }
386 }
387 id
388 }
389
390 #[doc(alias = "xmlNewChild")]
392 pub fn xml_new_child(
393 &mut self,
394 parent: NodeId,
395 ns_uri: Option<&str>,
396 name: &str,
397 content: Option<&str>,
398 ) -> NodeId {
399 let id = self.xml_new_doc_node(ns_uri, name, content);
400 self.xml_add_child(parent, id);
401 id
402 }
403
404 #[doc(alias = "xmlAddChild")]
406 pub fn xml_add_child(&mut self, parent: NodeId, child: NodeId) {
407 if child == parent {
408 return;
409 }
410 self.xml_unlink_node(child);
411 self.node_mut(child).parent = Some(parent);
412 let last = self.node(parent).last_child;
413 if let Some(l) = last {
414 self.node_mut(l).next_sibling = Some(child);
415 self.node_mut(child).prev_sibling = Some(l);
416 } else {
417 self.node_mut(parent).first_child = Some(child);
418 }
419 self.node_mut(parent).last_child = Some(child);
420 if parent == NodeId::DOCUMENT && self.kind(child) == NodeKind::Element {
421 self.root = Some(child);
422 }
423 }
424
425 #[doc(alias = "xmlAddNextSibling")]
427 pub fn xml_add_next_sibling(&mut self, cur: NodeId, elem: NodeId) {
428 self.xml_unlink_node(elem);
429 let parent = self.node(cur).parent;
430 let next = self.node(cur).next_sibling;
431 self.node_mut(elem).parent = parent;
432 self.node_mut(elem).prev_sibling = Some(cur);
433 self.node_mut(elem).next_sibling = next;
434 self.node_mut(cur).next_sibling = Some(elem);
435 if let Some(n) = next {
436 self.node_mut(n).prev_sibling = Some(elem);
437 } else if let Some(p) = parent {
438 self.node_mut(p).last_child = Some(elem);
439 }
440 }
441
442 #[doc(alias = "xmlAddPrevSibling")]
444 pub fn xml_add_prev_sibling(&mut self, cur: NodeId, elem: NodeId) {
445 self.xml_unlink_node(elem);
446 let parent = self.node(cur).parent;
447 let prev = self.node(cur).prev_sibling;
448 self.node_mut(elem).parent = parent;
449 self.node_mut(elem).next_sibling = Some(cur);
450 self.node_mut(elem).prev_sibling = prev;
451 self.node_mut(cur).prev_sibling = Some(elem);
452 if let Some(p) = prev {
453 self.node_mut(p).next_sibling = Some(elem);
454 } else if let Some(par) = parent {
455 self.node_mut(par).first_child = Some(elem);
456 }
457 }
458
459 #[doc(alias = "xmlUnlinkNode")]
461 pub fn xml_unlink_node(&mut self, id: NodeId) {
462 if id == NodeId::DOCUMENT {
463 return;
464 }
465 let parent = self.node(id).parent;
466 let prev = self.node(id).prev_sibling;
467 let next = self.node(id).next_sibling;
468 if let Some(p) = prev {
469 self.node_mut(p).next_sibling = next;
470 }
471 if let Some(n) = next {
472 self.node_mut(n).prev_sibling = prev;
473 }
474 if let Some(par) = parent {
475 if self.node(par).first_child == Some(id) {
476 self.node_mut(par).first_child = next;
477 }
478 if self.node(par).last_child == Some(id) {
479 self.node_mut(par).last_child = prev;
480 }
481 }
482 if self.root == Some(id) {
483 self.root = None;
484 }
485 self.node_mut(id).parent = None;
486 self.node_mut(id).prev_sibling = None;
487 self.node_mut(id).next_sibling = None;
488 }
489
490 #[doc(alias = "xmlReplaceNode")]
492 pub fn xml_replace_node(&mut self, old: NodeId, new: NodeId) -> NodeId {
493 self.xml_add_next_sibling(old, new);
494 self.xml_unlink_node(old);
495 new
496 }
497
498 pub fn add_attr_owned(
502 &mut self,
503 elem: NodeId,
504 name: String,
505 prefix: Option<String>,
506 value: String,
507 ) -> NodeId {
508 let id = self.alloc(NodeKind::Attribute, name);
509 self.node_mut(id).prefix = prefix;
510 self.node_mut(id).content = value;
511 self.node_mut(id).parent = Some(elem);
512 let last = self.node(elem).last_attr;
513 if let Some(l) = last {
514 self.node_mut(l).next_sibling = Some(id);
515 self.node_mut(id).prev_sibling = Some(l);
516 } else {
517 self.node_mut(elem).first_attr = Some(id);
518 }
519 self.node_mut(elem).last_attr = Some(id);
520 id
521 }
522
523 pub fn add_attr(&mut self, elem: NodeId, name: &str, prefix: Option<&str>, value: &str) -> NodeId {
524 let id = self.alloc(NodeKind::Attribute, name);
525 self.node_mut(id).prefix = prefix.map(str::to_string);
526 self.node_mut(id).content = value.to_string();
527 self.node_mut(id).parent = Some(elem);
528 let last = self.node(elem).last_attr;
529 if let Some(l) = last {
530 self.node_mut(l).next_sibling = Some(id);
531 self.node_mut(id).prev_sibling = Some(l);
532 } else {
533 self.node_mut(elem).first_attr = Some(id);
534 }
535 self.node_mut(elem).last_attr = Some(id);
536 id
537 }
538
539 pub fn push_ns_def(&mut self, elem: NodeId, prefix: Option<String>, uri: String) {
540 self.node_mut(elem).ns_defs.push((prefix, uri));
541 }
542
543 #[doc(alias = "xmlSetProp")]
545 pub fn xml_set_prop(&mut self, node: NodeId, name: &str, value: &str) -> NodeId {
546 let mut a = self.first_attr(node);
547 while let Some(id) = a {
548 if self.node(id).prefix.is_none() && self.node(id).name == name {
549 self.node_mut(id).content = value.to_string();
550 return id;
551 }
552 a = self.next_sibling(id);
553 }
554 self.add_attr(node, name, None, value)
555 }
556
557 #[doc(alias = "xmlGetProp")]
559 pub fn xml_get_prop(&self, node: NodeId, name: &str) -> Option<String> {
560 let mut a = self.first_attr(node);
561 while let Some(id) = a {
562 if self.node(id).prefix.is_none() && self.node(id).name == name {
563 return Some(self.node(id).content.clone());
564 }
565 a = self.next_sibling(id);
566 }
567 None
568 }
569
570 #[doc(alias = "xmlHasProp")]
572 pub fn xml_has_prop(&self, node: NodeId, name: &str) -> bool {
573 self.xml_get_prop(node, name).is_some()
574 }
575
576 #[doc(alias = "xmlUnsetProp")]
578 pub fn xml_unset_prop(&mut self, node: NodeId, name: &str) -> bool {
579 let mut a = self.first_attr(node);
580 let mut prev: Option<NodeId> = None;
581 while let Some(id) = a {
582 let next = self.next_sibling(id);
583 if self.node(id).prefix.is_none() && self.node(id).name == name {
584 if let Some(p) = prev {
585 self.node_mut(p).next_sibling = next;
586 } else {
587 self.node_mut(node).first_attr = next;
588 }
589 if next.is_none() {
590 self.node_mut(node).last_attr = prev;
591 }
592 if let Some(n) = next {
593 self.node_mut(n).prev_sibling = prev;
594 }
595 self.node_mut(id).parent = None;
596 self.node_mut(id).prev_sibling = None;
597 self.node_mut(id).next_sibling = None;
598 return true;
599 }
600 prev = Some(id);
601 a = next;
602 }
603 false
604 }
605
606 #[doc(alias = "xmlNodeGetContent")]
608 pub fn xml_node_get_content(&self, id: NodeId) -> String {
609 match self.kind(id) {
610 NodeKind::Text | NodeKind::CData | NodeKind::Comment | NodeKind::Pi | NodeKind::Attribute => {
611 self.content(id).to_string()
612 }
613 _ => {
614 let mut out = String::new();
615 self.collect_text(id, &mut out);
616 out
617 }
618 }
619 }
620
621 fn collect_text(&self, id: NodeId, out: &mut String) {
622 let mut c = self.first_child(id);
623 while let Some(ch) = c {
624 match self.kind(ch) {
625 NodeKind::Text | NodeKind::CData => out.push_str(self.content(ch)),
626 NodeKind::Element => self.collect_text(ch, out),
627 _ => {}
628 }
629 c = self.next_sibling(ch);
630 }
631 }
632
633 #[doc(alias = "xmlNodeSetContent")]
635 pub fn xml_node_set_content(&mut self, id: NodeId, content: &str) {
636 match self.kind(id) {
637 NodeKind::Text | NodeKind::CData | NodeKind::Comment | NodeKind::Pi | NodeKind::Attribute => {
638 self.node_mut(id).content = content.to_string();
639 }
640 _ => {
641 let mut c = self.first_child(id);
642 while let Some(ch) = c {
643 let next = self.next_sibling(ch);
644 self.xml_unlink_node(ch);
645 c = next;
646 }
647 if !content.is_empty() {
648 let t = self.alloc(NodeKind::Text, "#text");
649 self.node_mut(t).content = content.to_string();
650 self.xml_add_child(id, t);
651 }
652 }
653 }
654 }
655
656 #[doc(alias = "xmlIsBlankNode")]
658 pub fn xml_is_blank_node(&self, id: NodeId) -> bool {
659 match self.kind(id) {
660 NodeKind::Text | NodeKind::CData => self.content(id).chars().all(|c| {
661 c == ' ' || c == '\t' || c == '\n' || c == '\r'
662 }),
663 _ => false,
664 }
665 }
666
667 #[doc(alias = "xmlSearchNs")]
669 pub fn xml_search_ns(&self, node: NodeId, prefix: Option<&str>) -> Option<String> {
670 if prefix == Some("xml") {
671 return Some("http://www.w3.org/XML/1998/namespace".into());
672 }
673 if prefix == Some("xmlns") {
674 return Some("http://www.w3.org/2000/xmlns/".into());
675 }
676 let mut cur = Some(node);
677 while let Some(id) = cur {
678 for (p, uri) in self.ns_defs(id) {
679 if p.as_deref() == prefix {
680 return Some(uri.clone());
681 }
682 }
683 cur = self.parent(id);
684 }
685 None
686 }
687
688 #[doc(alias = "xmlNewNs")]
690 pub fn xml_new_ns(&mut self, node: NodeId, href: &str, prefix: Option<&str>) {
691 self.push_ns_def(node, prefix.map(str::to_string), href.to_string());
692 }
693
694 #[doc(alias = "xmlSetNs")]
696 pub fn xml_set_ns(&mut self, node: NodeId, href: Option<&str>, prefix: Option<&str>) {
697 self.node_mut(node).ns_uri = href.map(str::to_string);
698 self.node_mut(node).prefix = prefix.map(str::to_string);
699 }
700
701 #[doc(alias = "xmlCopyDoc")]
703 pub fn xml_copy_doc(&self) -> XmlDoc {
704 self.clone()
705 }
706
707 pub fn qname(&self, id: NodeId) -> String {
708 match self.prefix(id) {
709 Some(p) => format!("{}:{}", p, self.name(id)),
710 None => self.name(id).to_string(),
711 }
712 }
713
714 pub fn children(&self, id: NodeId) -> NodeIter<'_> {
715 NodeIter {
716 doc: self,
717 next: self.first_child(id),
718 }
719 }
720
721 pub fn attrs(&self, id: NodeId) -> NodeIter<'_> {
722 NodeIter {
723 doc: self,
724 next: self.first_attr(id),
725 }
726 }
727
728 pub fn len(&self) -> usize {
729 self.nodes.len()
730 }
731}
732
733pub struct NodeIter<'a> {
735 doc: &'a XmlDoc,
736 next: Option<NodeId>,
737}
738
739impl Iterator for NodeIter<'_> {
740 type Item = NodeId;
741
742 fn next(&mut self) -> Option<Self::Item> {
743 let n = self.next?;
744 self.next = self.doc.next_sibling(n);
745 Some(n)
746 }
747}
748
749#[doc(alias = "xmlFreeDoc")]
751pub fn xml_free_doc(_doc: XmlDoc) {}
752
753impl XmlDoc {
754 pub fn xml_copy_children_from(
765 &mut self,
766 src: &XmlDoc,
767 src_parent: NodeId,
768 dst_parent: NodeId,
769 ) {
770 let mut stack: Vec<(NodeId, NodeId)> = Vec::new();
772 let mut c = src.last_child(src_parent);
773 while let Some(x) = c {
774 stack.push((x, dst_parent));
775 c = src.prev_sibling(x);
776 }
777 while let Some((s, parent)) = stack.pop() {
778 let n = src.node(s);
779 let copy = self.alloc(n.kind, n.name.clone());
780 {
781 let d = self.node_mut(copy);
782 d.prefix = n.prefix.clone();
783 d.ns_uri = n.ns_uri.clone();
784 d.content = n.content.clone();
785 d.ns_defs = n.ns_defs.clone();
786 }
787 self.xml_add_child(parent, copy);
788 if src.reference_text.contains(&s) {
793 self.reference_text.insert(copy);
794 }
795 let mut a = src.first_attr(s);
797 while let Some(x) = a {
798 let an = src.node(x);
799 let (nm, pre, val, uri) = (
800 an.name.clone(),
801 an.prefix.clone(),
802 an.content.clone(),
803 an.ns_uri.clone(),
804 );
805 let ac = self.add_attr_owned(copy, nm, pre, val);
806 self.node_mut(ac).ns_uri = uri;
807 a = src.next_sibling(x);
808 }
809 let mut k = src.last_child(s);
810 while let Some(x) = k {
811 stack.push((x, copy));
812 k = src.prev_sibling(x);
813 }
814 }
815 }
816}