pub struct Xot { /* private fields */ }
Expand description
The Xot
struct manages all XML tree data in your program. It lets you
access and manipulate one or more XML documents and
fragments, as well as unattached trees of nodes.
Xot is implemented in several sections focusing on different aspects of accessing and manipulating XML data.
The Xot struct documentation is divided into different sections:
Implementations§
Source§impl Xot
§Read-only access
These are functions that provide read-only access to the tree.
impl Xot
§Read-only access
These are functions that provide read-only access to the tree.
Sourcepub fn document_element(&self, node: Node) -> Result<Node, Error>
pub fn document_element(&self, node: Node) -> Result<Node, Error>
Obtain the document element from the document node.
Returns Error::NotDocument
error if this is not the document node.
This accepts document nodes representing fragments. If the fragment has
multiple elements, it returns the first element. If the fragment has no
elements, it errors with Error::NoElementAtTopLevel
.
let mut xot = xot::Xot::new();
let doc = xot.parse("<p>Example</p>").unwrap();
let doc_el = xot.document_element(doc).unwrap();
// Check that we indeed have the `p` element
let p_name = xot.name("p").unwrap();
assert_eq!(xot.element(doc_el).unwrap().name(), p_name);
Sourcepub fn validate_well_formed_document(&self, node: Node) -> Result<(), Error>
pub fn validate_well_formed_document(&self, node: Node) -> Result<(), Error>
Given a node indicating a document, check if it is a well-formed document.
This checks that the document has a single document element, and that there are no text nodes as the top level. If it is a a well-formed document, this produces no errors.
If this is not supplied with a document node,
this produces a Error::NotDocument
error.
If there are no elements at the top level, this produces a
Error::NoElementAtTopLevel
error.
If there are multiple elements at the top level, this produces a
Error::MultipleElementsAtTopLevel
error.
If there is a text node at the top level, this produces a
Error::TextAtTopLevel
error.
If there is a illegal content (a namespace node, an attribute node
or a document node) at the top level under a document node,
this produces a Error::IllegalAtTopLevel
error.
Sourcepub fn top_element(&self, node: Node) -> Node
pub fn top_element(&self, node: Node) -> Node
Obtain top element, given node anywhere in a tree.
In an XML document this is the document element. In a XML document fragment this is the top element, but it may have siblings. If it’s an unattached tree, it’s the top node of that tree
Sourcepub fn root(&self, node: Node) -> Node
pub fn root(&self, node: Node) -> Node
Obtain root of the tree.
This is the document node if possible (in a document or fragment), but in an unattached tree this is the root of that tree.
Sourcepub fn is_removed(&self, node: Node) -> bool
pub fn is_removed(&self, node: Node) -> bool
Check whether a node has been removed.
This can happen because you removed it explicitly, or because you held
on to a reference and the node was replaced using Xot::replace
, or
unwrapped using Xot::element_unwrap
.
let mut xot = xot::Xot::new();
let root = xot.parse("<p>Example</p>").unwrap();
let p = xot.document_element(root).unwrap();
let text = xot.first_child(p).unwrap();
xot.remove(text);
assert_eq!(xot.to_string(root).unwrap(), "<p/>");
assert!(xot.is_removed(text));
Sourcepub fn parent(&self, node: Node) -> Option<Node>
pub fn parent(&self, node: Node) -> Option<Node>
Get parent node.
Returns None
if this is the document node or if the node is
unattached to a document.
Attribute and namespace nodes have a parent, even though they aren’t children of the element they are in.
let mut xot = xot::Xot::new();
let root = xot.parse("<p>Example</p>").unwrap();
let p = xot.document_element(root).unwrap();
let text = xot.first_child(p).unwrap();
assert_eq!(xot.parent(text), Some(p));
assert_eq!(xot.parent(p), Some(root));
assert_eq!(xot.parent(root), None);
Sourcepub fn attributes(&self, node: Node) -> Attributes<'_>
pub fn attributes(&self, node: Node) -> Attributes<'_>
Attributes accessor.
Returns a map of crate::NameId
to a String reference representing the
attributes on the element.
Note that if this is called on a non-element node, you get an empty map.
let mut xot = xot::Xot::new();
let a = xot.add_name("a");
let root = xot.parse(r#"<p a="A">Example</p>"#).unwrap();
let p = xot.document_element(root).unwrap();
let attributes = xot.attributes(p);
assert_eq!(attributes.get(a), Some(&"A".to_string()));
Sourcepub fn get_attribute(&self, node: Node, name: NameId) -> Option<&str>
pub fn get_attribute(&self, node: Node, name: NameId) -> Option<&str>
Get the attribute value for a name.
Note that if this is invoked non a non-element it’s always going to return None
Sourcepub fn namespaces(&self, node: Node) -> Namespaces<'_>
pub fn namespaces(&self, node: Node) -> Namespaces<'_>
Namespaces accessor.
Returns a map of crate::PrefixId
to crate::NamespaceId
representing
the namespace declarations on the element.
Note that if this is called on a non-element node, you get an empty map.
let mut xot = xot::Xot::new();
let foo_prefix = xot.add_prefix("foo");
let foo_ns = xot.add_namespace("FOO");
let root = xot.parse(r#"<p xmlns:foo="FOO">Example</p>"#).unwrap();
let p = xot.document_element(root).unwrap();
let namespaces = xot.namespaces(p);
assert_eq!(namespaces.get(foo_prefix), Some(&foo_ns));
Sourcepub fn get_namespace(&self, node: Node, prefix: PrefixId) -> Option<NamespaceId>
pub fn get_namespace(&self, node: Node, prefix: PrefixId) -> Option<NamespaceId>
Get the namespace for a prefix.
Note that if this is invoked non a non-element it’s always going to return None
Sourcepub fn prefixes(&self, node: Node) -> Prefixes
pub fn prefixes(&self, node: Node) -> Prefixes
Copy the namespace declarations as a prefixes hash table.
Sometimes it’s more convenient to work with a hash table of
prefixes as opposed to the dynamic Xot::namespaces
node map.
Sourcepub fn namespace_declarations(&self, node: Node) -> Vec<(PrefixId, NamespaceId)>
pub fn namespace_declarations(&self, node: Node) -> Vec<(PrefixId, NamespaceId)>
Copy the namespace declarations as a namespace declarations vec.
Sourcepub fn attribute_nodes(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn attribute_nodes(&self, node: Node) -> impl Iterator<Item = Node> + '_
Access the attribute nodes directly.
Sourcepub fn first_child(&self, node: Node) -> Option<Node>
pub fn first_child(&self, node: Node) -> Option<Node>
Get first child.
Returns None
if there are no children.
let mut xot = xot::Xot::new();
let root = xot.parse("<p>Example</p>").unwrap();
let p = xot.document_element(root).unwrap();
let text = xot.first_child(p).unwrap();
assert_eq!(xot.first_child(root), Some(p));
assert_eq!(xot.first_child(p), Some(text));
assert_eq!(xot.first_child(text), None);
Sourcepub fn last_child(&self, node: Node) -> Option<Node>
pub fn last_child(&self, node: Node) -> Option<Node>
Get last child.
Returns None
if there are no children.
Sourcepub fn next_sibling(&self, node: Node) -> Option<Node>
pub fn next_sibling(&self, node: Node) -> Option<Node>
Get next sibling.
Returns None
if there is no next sibling.
For normal child nodes, gives the next child.
For namespace and attribute nodes, gives the next namespace or attribute in definition order.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b/></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
assert_eq!(xot.next_sibling(b), None);
Sourcepub fn previous_sibling(&self, node: Node) -> Option<Node>
pub fn previous_sibling(&self, node: Node) -> Option<Node>
Get previous sibling.
Returns None
if there is no previous sibling.
Sourcepub fn ancestors(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn ancestors(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over ancestor nodes, including this one.
Namespace and attribute node have ancestors, even though they aren’t the child of the element they are in.
let mut xot = xot::Xot::new();
let root = xot.parse("<a><b><c/></b></a>").unwrap();
let a = xot.document_element(root).unwrap();
let b = xot.first_child(a).unwrap();
let c = xot.first_child(b).unwrap();
let ancestors = xot.ancestors(c).collect::<Vec<_>>();
assert_eq!(ancestors, vec![c, b, a, root]);
Sourcepub fn children(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn children(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over the child nodes of this node.
Namespace and attribute nodes aren’t consider child nodes even if they have a parent element.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b/></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
let children = xot.children(p).collect::<Vec<_>>();
assert_eq!(children, vec![a, b]);
Sourcepub fn child_index(&self, parent: Node, child: Node) -> Option<usize>
pub fn child_index(&self, parent: Node, child: Node) -> Option<usize>
Get index of child.
Returns None
if the node is not a child of this node, so
does not apply to namespace or attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b/></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
assert_eq!(xot.child_index(p, a), Some(0));
assert_eq!(xot.child_index(p, b), Some(1));
assert_eq!(xot.child_index(a, b), None);
Sourcepub fn reverse_children(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn reverse_children(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over the child nodes of this node, in reverse order.
Sourcepub fn descendants(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn descendants(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over of the descendants of this node, including this one. In document order (pre-order depth-first).
Namespace and attribute nodes aren’t included as descendants.
let mut xot = xot::Xot::new();
let root = xot.parse("<a><b><c/></b></a>").unwrap();
let a = xot.document_element(root).unwrap();
let b = xot.first_child(a).unwrap();
let c = xot.first_child(b).unwrap();
let descendants = xot.descendants(a).collect::<Vec<_>>();
assert_eq!(descendants, vec![a, b, c]);
Sourcepub fn all_descendants(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn all_descendants(&self, node: Node) -> impl Iterator<Item = Node> + '_
All the descendants of this node.
This includes this one, and namespace and attribute nodes, all in document order, where namespace nodes come before attribute nodes and attribute nodes come before normal children
Sourcepub fn reverse_preorder(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn reverse_preorder(&self, node: Node) -> impl Iterator<Item = Node> + '_
Reverse preorder traversal from node.
This starts with the given node, and then back to the root of the tree, in reverse preorder (document order) traversal. This means all nodes that exist previously in preorder are visited. It can be seen as the inverse of a descendants traversal.
Namespace and attribute nodes are not included in the traversal.
Sourcepub fn all_reverse_preorder(
&self,
node: Node,
) -> impl Iterator<Item = Node> + '_
pub fn all_reverse_preorder( &self, node: Node, ) -> impl Iterator<Item = Node> + '_
Reverse preorder traversal from node for all nodes.
Like Xot::reverse_preorder
but includes namespace and
attribute nodes too.
Sourcepub fn following_siblings(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn following_siblings(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over the following siblings of this node, including this one.
In case of namespace or attribute nodes, includes the following sibling namespace or attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b/><c/></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
let c = xot.next_sibling(b).unwrap();
let siblings = xot.following_siblings(a).collect::<Vec<_>>();
assert_eq!(siblings, vec![a, b, c]);
let siblings = xot.following_siblings(b).collect::<Vec<_>>();
assert_eq!(siblings, vec![b, c]);
Sourcepub fn preceding_siblings(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn preceding_siblings(&self, node: Node) -> impl Iterator<Item = Node> + '_
Iterator over the preceding siblings of this node.
Sourcepub fn following(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn following(&self, node: Node) -> impl Iterator<Item = Node> + '_
Following nodes in document order
These are nodes that come after this node in document order, without that node itself, its ancestors, or its descendants.
Does not include namespace or attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b><c/><d/><e/></b><f><g/><h/></f></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
let c = xot.first_child(b).unwrap();
let d = xot.next_sibling(c).unwrap();
let e = xot.next_sibling(d).unwrap();
let f = xot.next_sibling(b).unwrap();
let g = xot.first_child(f).unwrap();
let h = xot.next_sibling(g).unwrap();
let siblings = xot.following(c).collect::<Vec<_>>();
assert_eq!(siblings, vec![d, e, f, g, h]);
Sourcepub fn all_following(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn all_following(&self, node: Node) -> impl Iterator<Item = Node> + '_
Following nodes in document order.
Like Xot::following
but includes namespace and
attribute nodes too.
Sourcepub fn preceding(&self, node: Node) -> impl Iterator<Item = Node> + '_
pub fn preceding(&self, node: Node) -> impl Iterator<Item = Node> + '_
Preceding nodes in document order
These are nodes that come before this node in document order, without that node itself, its ancestors, or its descendants.
Does not include namespace or attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<p><a/><b><c/><d/><e/></b><f><g/><h/></f></p>").unwrap();
let p = xot.document_element(root).unwrap();
let a = xot.first_child(p).unwrap();
let b = xot.next_sibling(a).unwrap();
let c = xot.first_child(b).unwrap();
let d = xot.next_sibling(c).unwrap();
let e = xot.next_sibling(d).unwrap();
let f = xot.next_sibling(b).unwrap();
let g = xot.first_child(f).unwrap();
let h = xot.next_sibling(g).unwrap();
let siblings = xot.preceding(e).collect::<Vec<_>>();
assert_eq!(siblings, vec![d, c, a]);
let siblings = xot.preceding(h).collect::<Vec<_>>();
assert_eq!(siblings, vec![g, e, d, c, b, a]);
Sourcepub fn traverse(&self, node: Node) -> impl Iterator<Item = NodeEdge> + '_
pub fn traverse(&self, node: Node) -> impl Iterator<Item = NodeEdge> + '_
Traverse over node edges.
This can be used to traverse the tree in document order iteratively
without the need for recursion, while getting structure information
(unlike Xot::descendants
which doesn’t retain structure
information).
For the tree <a><b/></a>
this generates a NodeEdge::Start
for
<a>
, then a NodeEdge::Start
for <b>
, immediately followed by a
NodeEdge::End
for <b>
, and finally a NodeEdge::End
for <a>
.
For value types other than element or root, the start and end always come as pairs without any intervening edges.
This does not include edges for namespace and attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<a><b>Text</b></a>").unwrap();
let a = xot.document_element(root).unwrap();
let b = xot.first_child(a).unwrap();
let text = xot.first_child(b).unwrap();
let edges = xot.traverse(a).collect::<Vec<_>>();
assert_eq!(edges, vec![
xot::NodeEdge::Start(a),
xot::NodeEdge::Start(b),
xot::NodeEdge::Start(text),
xot::NodeEdge::End(text),
xot::NodeEdge::End(b),
xot::NodeEdge::End(a),
]);
Sourcepub fn all_traverse(&self, node: Node) -> impl Iterator<Item = NodeEdge> + '_
pub fn all_traverse(&self, node: Node) -> impl Iterator<Item = NodeEdge> + '_
Traverse nodes, including namespace and attribute nodes.
Sourcepub fn reverse_traverse(
&self,
node: Node,
) -> impl Iterator<Item = NodeEdge> + '_
pub fn reverse_traverse( &self, node: Node, ) -> impl Iterator<Item = NodeEdge> + '_
Traverse over node edges in reverse order.
Like Xot::traverse
but in reverse order.
Note that you still have to start with a top-level node, it just traverses through its descendants in a reverse order.
Sourcepub fn reverse_all_traverse(
&self,
node: Node,
) -> impl Iterator<Item = NodeEdge> + '_
pub fn reverse_all_traverse( &self, node: Node, ) -> impl Iterator<Item = NodeEdge> + '_
Traverse nodes, including namespace and attribute nodes, in reverse order.
This is like Xot::all_traverse
but includes namespace and
Sourcepub fn level_order(&self, node: Node) -> impl Iterator<Item = LevelOrder> + '_
pub fn level_order(&self, node: Node) -> impl Iterator<Item = LevelOrder> + '_
Traverse over nodes in level order.
This is a breath first traversal, where each level is visited in turn.
Sequences of nodes with a different parent are separated by
LevelOrder::End
.
For the tree <a><b><d/></b><c><e/></c></a>
this generates a
LevelOrder::Node
for <a>
, then a LevelOrder::End
. Next, a
LevelOrder::Node
for <b/>
and </c>
are generated, again
followed by a LevelOrder::End
. Then a LevelOrder::Node
is
generated for <d/>
, followed by a LevelOrder::End
. Finally a
LevelOrder::Node
is generated for <e/>
, followed by a
LevelOrder::End
.
This does not include namespace or attribute nodes.
let mut xot = xot::Xot::new();
let root = xot.parse("<a><b><d/></b><c><e/></c></a>").unwrap();
let a = xot.document_element(root).unwrap();
let b = xot.first_child(a).unwrap();
let d = xot.first_child(b).unwrap();
let c = xot.next_sibling(b).unwrap();
let e = xot.first_child(c).unwrap();
let levels = xot.level_order(a).collect::<Vec<_>>();
assert_eq!(levels, vec![
xot::LevelOrder::Node(a),
xot::LevelOrder::End,
xot::LevelOrder::Node(b),
xot::LevelOrder::Node(c),
xot::LevelOrder::End,
xot::LevelOrder::Node(d),
xot::LevelOrder::End,
xot::LevelOrder::Node(e),
xot::LevelOrder::End,
]);
Source§impl Xot
§Creation
These are functions to help create nodes.
impl Xot
§Creation
These are functions to help create nodes.
See also the convenience manipulation methods like Xot::append_element
in the manipulation section.
Sourcepub fn new_document(&mut self) -> Node
pub fn new_document(&mut self) -> Node
Create a new, unattached document node without document element.
You can use this to create a new document from scratch. If you don’t attach at a single element later, the document is going to be invalid.
use xot::Xot;
let mut xot = Xot::new();
let doc_name = xot.add_name("doc");
let doc_el = xot.new_element(doc_name);
let txt = xot.new_text("Hello, world!");
xot.append(doc_el, txt)?;
/// now create the document
let document = xot.new_document();
xot.append(document, doc_el)?;
assert_eq!(xot.to_string(document)?, "<doc>Hello, world!</doc>");
Sourcepub fn new_document_with_element(&mut self, node: Node) -> Result<Node, Error>
pub fn new_document_with_element(&mut self, node: Node) -> Result<Node, Error>
Create a new document node with a document element.
You can use this to create a new document from scratch. You have to
supply a document element. If you want to create an empty document node,
use Xot::new_document
.
use xot::Xot;
let mut xot = Xot::new();
let doc_name = xot.add_name("doc");
let doc_el = xot.new_element(doc_name);
let txt = xot.new_text("Hello, world!");
xot.append(doc_el, txt)?;
/// now create the document
let document = xot.new_document_with_element(doc_el)?;
assert_eq!(xot.to_string(document)?, "<doc>Hello, world!</doc>");
Sourcepub fn new_element(&mut self, name: impl Into<NameId>) -> Node
pub fn new_element(&mut self, name: impl Into<NameId>) -> Node
Create a new, unattached element node given element name.
You supply a crate::NameId
or a crate::xmlname
structure that
can be turned into a name id.
To create a potentially new name you can use Xot::add_name
or
Xot::add_name_ns
. If the name already exists the existing name id
is returned.
To reuse an existing name that has been previously used, you can use
Xot::name
or Xot::name_ns
.
use xot::Xot;
let mut xot = Xot::new();
let doc_name = xot.add_name("doc");
let doc_el = xot.new_element(doc_name);
let root = xot.new_document_with_element(doc_el)?;
assert_eq!(xot.to_string(root)?, "<doc/>");
With a namespaced element:
use xot::Xot;
let mut xot = Xot::new();
let ns = xot.add_namespace("http://example.com");
let ex = xot.add_prefix("ex");
// create name in namespace
let doc_name = xot.add_name_ns("doc", ns);
let doc_el = xot.new_element(doc_name);
// set up namepace prefix for element so it serializes to XML nicely
xot.namespaces_mut(doc_el).insert(ex, ns);
let root = xot.new_document_with_element(doc_el)?;
assert_eq!(xot.to_string(root)?, r#"<ex:doc xmlns:ex="http://example.com"/>"#);
Or with xmlname
:
use xot::{Xot, xmlname};
let mut xot = Xot::new();
let namespace = xmlname::CreateNamespace::new(&mut xot, "ex", "http://example.com");
let doc_name = xmlname::CreateName::namespaced(&mut xot, "doc", &namespace);
let doc_el = xot.new_element(doc_name);
// set up namepace prefix for element so it serializes to XML nicely
xot.append_namespace(doc_el, &namespace);
let root = xot.new_document_with_element(doc_el)?;
assert_eq!(xot.to_string(root)?, r#"<ex:doc xmlns:ex="http://example.com"/>"#);
Sourcepub fn new_text(&mut self, text: &str) -> Node
pub fn new_text(&mut self, text: &str) -> Node
Create a new, unattached text node.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let txt = xot.new_text("Hello, world!");
xot.append(doc_el, txt)?;
assert_eq!(xot.to_string(root)?, "<doc>Hello, world!</doc>");
Sourcepub fn new_comment(&mut self, comment: &str) -> Node
pub fn new_comment(&mut self, comment: &str) -> Node
Create a new, unattached comment node given comment text.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let comment = xot.new_comment("Hello, world!");
xot.append(doc_el, comment)?;
assert_eq!(xot.to_string(root)?, "<doc><!--Hello, world!--></doc>");
Sourcepub fn new_processing_instruction(
&mut self,
target: impl Into<NameId>,
data: Option<&str>,
) -> Node
pub fn new_processing_instruction( &mut self, target: impl Into<NameId>, data: Option<&str>, ) -> Node
Create a new, unattached processing instruction.
use xot::Xot;
let mut xot = Xot::new();
let target = xot.add_name("target");
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let pi = xot.new_processing_instruction(target, Some("data"));
xot.append(doc_el, pi)?;
assert_eq!(xot.to_string(root)?, r#"<doc><?target data?></doc>"#);
Sourcepub fn new_attribute_node(
&mut self,
name: impl Into<NameId>,
value: String,
) -> Node
pub fn new_attribute_node( &mut self, name: impl Into<NameId>, value: String, ) -> Node
Create a new, unattached attribute node.
You can then use Xot::append_attribute_node
to add it to an element node.
This method is useful in situations where attributes need to be created
independently of elements, but for many use cases you can use the
Xot::attributes_mut
API to create attributes instead.
use xot::Xot;
let mut xot = Xot::new();
let foo = xot.add_name("foo");
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let attr = xot.new_attribute_node(foo, "FOO".to_string());
xot.append_attribute_node(doc_el, attr)?;
assert_eq!(xot.to_string(root)?, r#"<doc foo="FOO"/>"#);
Sourcepub fn new_namespace_node(
&mut self,
prefix: PrefixId,
namespace: NamespaceId,
) -> Node
pub fn new_namespace_node( &mut self, prefix: PrefixId, namespace: NamespaceId, ) -> Node
Create a new, unattached namespace declaration node.
You can then use Xot::append_namespace_node
to add it to an element
node.
This method is useful in situations where namespaces need to be created
independently of elements, but for many use cases you can use the
Xot::namespaces_mut
API to create namespaces instead.
use xot::Xot;
let mut xot = Xot::new();
let foo = xot.add_prefix("foo");
let ns = xot.add_namespace("http://example.com");
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let ns = xot.new_namespace_node(foo, ns);
xot.append_namespace_node(doc_el, ns)?;
assert_eq!(xot.to_string(root)?, r#"<doc xmlns:foo="http://example.com"/>"#);
Source§impl Xot
§Manipulation
These methods maintain a well-formed XML structure:
impl Xot
§Manipulation
These methods maintain a well-formed XML structure:
- There is only one document element under the document node which cannot be removed.
- The only other nodes that can exist directly under the document node are comments and processing instructions.
- You cannot add a node to a node that is not an element or the document node.
Note that you can use these manipulation methods to move nodes between trees – if you append a node that’s in another tree, that node is first detached from the other tree before it’s inserted into the new location.
If text consolidation is enabled (the default), then also ensures that text nodes are consolidated: two text nodes never appear consecutively. If you add a text node after or before another text node, the text is appended to the existing text node, and the added text node is removed. This also happens if you remove a node causing two text nodes to be adjacent; the second text node is removed.
During parsing it’s also guaranteed that text and CDATA content that is adjacent is consolidated into a single node.
You can disable and enable text consolidation using
Xot::set_text_consolidation
.
Text node consolidation example:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc>First<s/>Second</doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let children = xot.children(doc_el).collect::<Vec<_>>();
let first = children[0];
let s = children[1];
let second = children[2];
// Now we remove s from the document
xot.remove(s)?;
// The text nodes are now adjacent, so the second text node is removed
// and merged with the first text node.
let children = xot.children(doc_el).collect::<Vec<_>>();
assert_eq!(children.len(), 1);
assert_eq!(xot.text_str(children[0]).unwrap(), "FirstSecond");
Sourcepub fn append(&mut self, parent: Node, child: Node) -> Result<(), Error>
pub fn append(&mut self, parent: Node, child: Node) -> Result<(), Error>
Append a child to the end of the children of the given parent.
It is now the new last node of the parent.
Append returns an error if you place a node in a location that is not allowed, such appending a node to a text node, or appending a new element to the root (there can be only one document element).
See also the convenience methods Xot::append_element
,
Xot::append_text
, Xot::append_comment
and
Xot::append_processing_instruction
.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><p>Example</p></doc>"#)?;
let doc_el = xot.document_element(root)?;
let p_name = xot.add_name("p");
let p_el = xot.new_element(p_name);
xot.append(doc_el, p_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc><p>Example</p><p/></doc>"#);
Sourcepub fn append_namespace_node(
&mut self,
parent: Node,
child: Node,
) -> Result<Node, Error>
pub fn append_namespace_node( &mut self, parent: Node, child: Node, ) -> Result<Node, Error>
Append namespace node to parent node.
If the namespace prefix already exists, instead of appending the node, updates the existing node.
Returns the node that was inserted, or if an existing node was updated, this node.
Note that an easier way to add namespace prefixes is through
Xot::namespaces_mut()
. This method is only useful if you have
independent namespace nodes.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let prefix = xot.add_prefix("foo");
let namespace = xot.add_namespace("http://example.com");
let namespace2 = xot.add_namespace("http://example.com/2");
let node = xot.new_namespace_node(prefix, namespace);
let added_node = xot.append_namespace_node(doc_el, node)?;
// since the node didn't yet exist, it's the node we got
assert_eq!(added_node, node);
assert_eq!(xot.to_string(root).unwrap(), r#"<doc xmlns:foo="http://example.com"/>"#);
// If we append a node with the same prefix, the existing one is
// updated.
let new_node = xot.new_namespace_node(prefix, namespace2);
let updated_node = xot.append_namespace_node(doc_el, new_node)?;
// the updated node is the original not, not the new node
assert_eq!(updated_node, node);
assert_ne!(updated_node, new_node);
assert_eq!(xot.to_string(root).unwrap(), r#"<doc xmlns:foo="http://example.com/2"/>"#);
Sourcepub fn append_namespace(
&mut self,
parent: Node,
namespace: &CreateNamespace,
) -> Result<Node, Error>
pub fn append_namespace( &mut self, parent: Node, namespace: &CreateNamespace, ) -> Result<Node, Error>
Append an xmlname::CreateNamespace
This creates a namespace node for the given namespace and prefix, and then returns this node (or previously updated node).
use xot::{Xot, xmlname};
let mut xot = Xot::new();
let namespace = xmlname::CreateNamespace::new(&mut xot, "foo", "http://example.com");
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
xot.append_namespace(doc_el, &namespace)?;
assert_eq!(xot.to_string(root).unwrap(), r#"<doc xmlns:foo="http://example.com"/>"#);
Sourcepub fn append_attribute_node(
&mut self,
parent: Node,
child: Node,
) -> Result<Node, Error>
pub fn append_attribute_node( &mut self, parent: Node, child: Node, ) -> Result<Node, Error>
Append attribute node to parent node.
If the attribute name already exists, instead of appending the node, updates the existing node.
Returns the node that was inserted, or if an existing node was updated, this node.
Note that an easier way to add attributes is through
Xot::attributes_mut()
. This method is only useful if you have
independent attribute nodes.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root)?;
let foo = xot.add_name("foo");
let node = xot.new_attribute_node(foo, "FOO".to_string());
let added_node = xot.append_attribute_node(doc_el, node)?;
// Since the node didn't yet exist, it's the one we get
assert_eq!(added_node, node);
assert_eq!(xot.to_string(root).unwrap(), r#"<doc foo="FOO"/>"#);
// If we append a node with the same name, the existing one is
// updated.
let new_node = xot.new_attribute_node(foo, "FOO2".to_string());
let updated_node = xot.append_attribute_node(doc_el, new_node)?;
// the updated node is the original not, not the new node
assert_eq!(updated_node, node);
assert_ne!(updated_node, new_node);
assert_eq!(xot.to_string(root).unwrap(), r#"<doc foo="FOO2"/>"#);
Sourcepub fn any_append(&mut self, parent: Node, child: Node) -> Result<Node, Error>
pub fn any_append(&mut self, parent: Node, child: Node) -> Result<Node, Error>
Append any node, including namespace and attribute nodes.
Namespace and attributes are appended in their respective places, and normal child nodes are appended in the end.
Returns the node that was appended or, in case of attributes or namespaces that already existed, updated.
Sourcepub fn append_text(&mut self, parent: Node, text: &str) -> Result<(), Error>
pub fn append_text(&mut self, parent: Node, text: &str) -> Result<(), Error>
Append a text node to a parent node given text.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><p>Example</p></doc>"#)?;
let doc_el = xot.document_element(root)?;
xot.append_text(doc_el, "Hello")?;
assert_eq!(xot.to_string(root)?, r#"<doc><p>Example</p>Hello</doc>"#);
Sourcepub fn append_element(
&mut self,
parent: Node,
name_id: NameId,
) -> Result<(), Error>
pub fn append_element( &mut self, parent: Node, name_id: NameId, ) -> Result<(), Error>
Append an element node to a parent node given a name.
Create a name id using Xot::add_name
or Xot::add_name_ns
, or
reuse an existing name id using Xot::name
, Xot::name_ns
.
Example:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let name_id = xot.add_name("foo");
xot.append_element(doc_el, name_id)?;
assert_eq!(xot.to_string(root)?, "<doc><foo/></doc>");
Sourcepub fn append_comment(
&mut self,
parent: Node,
comment: &str,
) -> Result<(), Error>
pub fn append_comment( &mut self, parent: Node, comment: &str, ) -> Result<(), Error>
Append a comment node to a parent node given comment text.
Sourcepub fn append_processing_instruction(
&mut self,
parent: Node,
target: NameId,
data: Option<&str>,
) -> Result<(), Error>
pub fn append_processing_instruction( &mut self, parent: Node, target: NameId, data: Option<&str>, ) -> Result<(), Error>
Append a processing instruction node to a parent node given target and data.
Sourcepub fn prepend(&mut self, parent: Node, child: Node) -> Result<(), Error>
pub fn prepend(&mut self, parent: Node, child: Node) -> Result<(), Error>
Prepend a child to the beginning of the children of the given parent.
It is now the new first node of the parent.
Sourcepub fn insert_after(
&mut self,
reference_node: Node,
new_sibling: Node,
) -> Result<(), Error>
pub fn insert_after( &mut self, reference_node: Node, new_sibling: Node, ) -> Result<(), Error>
Insert a new sibling after a reference node.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a/><c/></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
let b_name = xot.add_name("b");
let b_el = xot.new_element(b_name);
xot.insert_after(a_el, b_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc><a/><b/><c/></doc>"#);
Sourcepub fn insert_before(
&mut self,
reference_node: Node,
new_sibling: Node,
) -> Result<(), Error>
pub fn insert_before( &mut self, reference_node: Node, new_sibling: Node, ) -> Result<(), Error>
Insert a new sibling before a reference node.
Sourcepub fn detach(&mut self, node: Node) -> Result<(), Error>
pub fn detach(&mut self, node: Node) -> Result<(), Error>
Detach a node (and its descendants) from the tree.
It now becomes an unattached tree (without top-level document node).
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a><b><c/></b></a></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
xot.detach(a_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc/>"#);
assert_eq!(xot.to_string(a_el)?, r#"<a><b><c/></b></a>"#);
// a_al still exist; it's not removed like with [`Xot::remove`].
assert!(!xot.is_removed(a_el));
Sourcepub fn remove(&mut self, node: Node) -> Result<(), Error>
pub fn remove(&mut self, node: Node) -> Result<(), Error>
Remove a node (and its descendants) from the tree
This removes the nodes from Xot. Trying to access or
manipulate a removed node results in a panic. You can verify
that a node is removed by using Xot::is_removed
.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a><b><c/></b></a></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
xot.remove(a_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc/>"#);
// a_al is removed; it's not detached like with [`Xot::detach`].
assert!(xot.is_removed(a_el));
Sourcepub fn set_element_name(&mut self, node: Node, name_id: NameId)
pub fn set_element_name(&mut self, node: Node, name_id: NameId)
Set the element name of a node.
If this node is not an element, panic.
Sourcepub fn namespaces_mut(&mut self, node: Node) -> MutableNamespaces<'_>
pub fn namespaces_mut(&mut self, node: Node) -> MutableNamespaces<'_>
Mutable namespaces accessor.
Panics if called on a non-element.
Use this to set namespace prefix declarations on an element. You use a hashmap-like API:
let mut xot = xot::Xot::new();
let foo_prefix = xot.add_prefix("foo");
let foo_ns = xot.add_namespace("FOO");
let root = xot.parse(r#"<p>Example</p>"#).unwrap();
let p = xot.document_element(root).unwrap();
let mut namespaces = xot.namespaces_mut(p);
namespaces.insert(foo_prefix, foo_ns);
assert_eq!(xot.to_string(root).unwrap(), r#"<p xmlns:foo="FOO">Example</p>"#);
Sourcepub fn set_namespace(&mut self, node: Node, prefix: PrefixId, ns: NamespaceId)
pub fn set_namespace(&mut self, node: Node, prefix: PrefixId, ns: NamespaceId)
Set namespace for a prefix on an element.
Note that if this is invoked on a non-element it’s going to panic.
Sourcepub fn remove_namespace(&mut self, node: Node, prefix: PrefixId)
pub fn remove_namespace(&mut self, node: Node, prefix: PrefixId)
Remove namespace for an element, if it exists
Note that if this is invoked on a non-element it’s going to panic.
Sourcepub fn attributes_mut(&mut self, node: Node) -> MutableAttributes<'_>
pub fn attributes_mut(&mut self, node: Node) -> MutableAttributes<'_>
Mutable attributes accessor
Panics if called on a non-element.
Use this if you want to set an attribute on an element. You use a hashmap-like API:
let mut xot = xot::Xot::new();
let a = xot.add_name("a");
let root = xot.parse(r#"<p>Example</p>"#).unwrap();
let p = xot.document_element(root).unwrap();
let mut attributes = xot.attributes_mut(p);
attributes.insert(a, "A".to_string());
assert_eq!(xot.to_string(root).unwrap(), r#"<p a="A">Example</p>"#);
Sourcepub fn set_attribute(
&mut self,
node: Node,
name: NameId,
value: impl Into<String>,
)
pub fn set_attribute( &mut self, node: Node, name: NameId, value: impl Into<String>, )
Set attribute on an element.
Note that if this is invoked on a non-element it’s going to panic.
Sourcepub fn remove_attribute(&mut self, node: Node, name: NameId)
pub fn remove_attribute(&mut self, node: Node, name: NameId)
Remove attribute from an element, if it exists
Note that if this is invoked on a non-element it’s going to panic.
Sourcepub fn clone_node(&mut self, node: Node) -> Node
pub fn clone_node(&mut self, node: Node) -> Node
Clone a node and its descendants into a new unattached tree.
The cloned nodes are not attached to anything. If you clone a document node, you clone the whole document (or fragment).
This does not include any namespace prefix information defined in any
ancestors of the cloned node. If you want to preserve such prefix
information, see Xot::clone_with_prefixes
.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a f="F"><b><c/></b></a></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
let cloned = xot.clone_node(a_el);
assert_eq!(xot.to_string(root)?, r#"<doc><a f="F"><b><c/></b></a></doc>"#);
// cloned is not attached to anything
assert!(xot.parent(cloned).is_none());
// cloned is a new unattached tree which you can serialize
assert_eq!(xot.to_string(cloned)?, r#"<a f="F"><b><c/></b></a>"#);
Sourcepub fn clone_with_prefixes(&mut self, node: Node) -> Node
pub fn clone_with_prefixes(&mut self, node: Node) -> Node
Clone a node and its descendants into a new unattached tree.
If the cloned node is an element, required namespace prefixes that are in scope are added to the cloned node. Only those namespaces that are in fact in use in the node or descendants are added.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc xmlns:foo="http://example.com"><foo:a><foo:b><foo:c/></foo:b></foo:a></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
let cloned = xot.clone_with_prefixes(a_el);
assert_eq!(xot.to_string(cloned)?, r#"<foo:a xmlns:foo="http://example.com"><foo:b><foo:c/></foo:b></foo:a>"#);
// if you do a normal clone, prefixes aren't preserved and need to be generated instead
let cloned = xot.clone_node(a_el);
xot.create_missing_prefixes(cloned)?;
assert_eq!(xot.to_string(cloned)?, r#"<n0:a xmlns:n0="http://example.com"><n0:b><n0:c/></n0:b></n0:a>"#);
Sourcepub fn element_unwrap(&mut self, node: Node) -> Result<(), Error>
pub fn element_unwrap(&mut self, node: Node) -> Result<(), Error>
Unwrap an element; its children are moved to its parent.
The unwrapped element itself is removed.
You can unwrap the document element, but only if that document has exactly 1 child that is an element.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a><b><c/></b></a></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
xot.element_unwrap(a_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc><b><c/></b></doc>"#);
Sourcepub fn element_wrap(
&mut self,
node: Node,
name_id: NameId,
) -> Result<Node, Error>
pub fn element_wrap( &mut self, node: Node, name_id: NameId, ) -> Result<Node, Error>
Wrap a node in a new element
Returns the node for the new wrapping element.
It’s not allowed to wrap the document node. It’s allowed to wrap the document element but not any comment or processing instruction nodes directly under the document.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><b><c/></b></doc>"#)?;
let doc_el = xot.document_element(root)?;
let b_el = xot.first_child(doc_el).unwrap();
let a_name = xot.add_name("a");
let wrapper = xot.element_wrap(b_el, a_name)?;
assert_eq!(xot.to_string(root)?, r#"<doc><a><b><c/></b></a></doc>"#);
assert_eq!(xot.to_string(wrapper)?, r#"<a><b><c/></b></a>"#);
Sourcepub fn replace(
&mut self,
replaced_node: Node,
replacing_node: Node,
) -> Result<(), Error>
pub fn replace( &mut self, replaced_node: Node, replacing_node: Node, ) -> Result<(), Error>
Replace a node with another one.
The replaced node and all its descendants are removed.
This works for any node, except the document node itself.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a><b/></a><c/></doc>"#)?;
let doc_el = xot.document_element(root)?;
let a_el = xot.first_child(doc_el).unwrap();
let d_name = xot.add_name("d");
let d_el = xot.new_element(d_name);
xot.replace(a_el, d_el)?;
assert_eq!(xot.to_string(root)?, r#"<doc><d/><c/></doc>"#);
Sourcepub fn set_text_consolidation(&mut self, consolidate: bool)
pub fn set_text_consolidation(&mut self, consolidate: bool)
Set text consolidation
By default, text nodes are consolidated when possible. You can turn off this behavior so text nodes are never merged by calling this.
Sourcepub fn remove_insignificant_whitespace(&mut self, node: Node)
pub fn remove_insignificant_whitespace(&mut self, node: Node)
Remove insignificant whitespace
XML officially does not have a notion of insignificant whitespace, but here we employ the following one: a text node can be removed if it contains only whitespace and has no text sibling that contains non-whitespace text.
Source§impl Xot
§Names, namespaces and prefixes.
Xot does not let you use names, prefixes and URIs directly. Instead you use
the types NameId
, NamespaceId
and PrefixId
to refer to these.
impl Xot
§Names, namespaces and prefixes.
Xot does not let you use names, prefixes and URIs directly. Instead you use
the types NameId
, NamespaceId
and PrefixId
to refer to these.
This has some advantages:
-
It’s faster to compare and hash names, namespaces and prefixes.
-
It takes less memory to store a tree.
-
You get type-checks and can’t mix up names, namespaces and prefixes.
Names, namespaces and prefixes are shared in a single Xot, so are the same
in multiple trees. This makes it safe to copy and move nodes between trees.
If you care about the readability of the serialized XML you do need to
ensure that each tree uses xmlns
attributes to declare the namespaces it
uses; otherwise prefixes are generated during serialization.
The minor drawback is that you need to use multiple steps to create a name, prefix or namespace for use, or to access the string value of a name, prefix or namepace. This drawback may be an advantage at times, as typical code needs to use a single name, namespace or prefix multiple times, so assigning to a variable is more convenient than repeating strings.
There are also APIs that help with namespace access and manipulation in
other sections: Xot::namespaces
, Xot::namespaces_mut
, and
Xot::get_namespace
, Xot::set_namespace
and
Xot::remove_namespace
, and Xot::append_namespace_node
.
Sourcepub fn name(&self, name: &str) -> Option<NameId>
pub fn name(&self, name: &str) -> Option<NameId>
Look up name without a namespace.
This is the immutable version of Xot::add_name
; it returns
None
if the name doesn’t exist.
use xot::Xot;
let mut xot = Xot::new();
assert!(xot.name("z").is_none());
let name = xot.add_name("z");
assert_eq!(xot.name("z"), Some(name));
Sourcepub fn add_name(&mut self, name: &str) -> NameId
pub fn add_name(&mut self, name: &str) -> NameId
Add name without a namespace.
If the name already exists, return its id, otherwise creates it.
use xot::Xot;
let mut xot = Xot::new();
let name = xot.add_name("a");
// the namespace is "" for no namespace
assert_eq!(xot.name_ns_str(name), ("a", ""));
let root = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(root).unwrap();
// add an element, using the name
let node = xot.append_element(doc_el, name)?;
assert_eq!(xot.to_string(root)?, "<doc><a/></doc>");
Sourcepub fn name_ns(&self, name: &str, namespace_id: NamespaceId) -> Option<NameId>
pub fn name_ns(&self, name: &str, namespace_id: NamespaceId) -> Option<NameId>
Look up name with a namespace.
use xot::Xot;
let mut xot = Xot::new();
let ns = xot.add_namespace("http://example.com");
let name = xot.add_name_ns("a", ns);
assert_eq!(xot.name_ns_str(name), ("a", "http://example.com"));
Look up name of an element:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc xmlns="http://example.com"><a/></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let doc_value = xot.element(doc_el).unwrap();
// get the name of the element
let name = xot.name_ns_str(doc_value.name());
Sourcepub fn add_name_ns(&mut self, name: &str, namespace_id: NamespaceId) -> NameId
pub fn add_name_ns(&mut self, name: &str, namespace_id: NamespaceId) -> NameId
Add name with a namespace.
If the name already exists, return its id.
use xot::Xot;
let mut xot = Xot::new();
let ns = xot.add_namespace("http://example.com");
let name_a = xot.add_name_ns("a", ns);
let root = xot.parse(r#"<doc xmlns="http://example.com"><a/></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let doc_value = xot.element(doc_el).unwrap();
let a_value = xot.element(a_el).unwrap();
// we know a is the right name, but doc is not
assert_eq!(a_value.name(), name_a);
assert_ne!(doc_value.name(), name_a);
Sourcepub fn namespace(&self, namespace: &str) -> Option<NamespaceId>
pub fn namespace(&self, namespace: &str) -> Option<NamespaceId>
Look up namespace.
This is the immutable version of Xot::add_namespace
; it returns
None
if the namespace doesn’t exist.
Sourcepub fn add_namespace(&mut self, namespace: &str) -> NamespaceId
pub fn add_namespace(&mut self, namespace: &str) -> NamespaceId
Add namespace.
If the namespace already exists, return its id.
Sourcepub fn prefix(&self, prefix: &str) -> Option<PrefixId>
pub fn prefix(&self, prefix: &str) -> Option<PrefixId>
Look up prefix.
This is the immutable version of Xot::add_prefix
; it returns
None
if the prefix doesn’t exist.
Sourcepub fn add_prefix(&mut self, prefix: &str) -> PrefixId
pub fn add_prefix(&mut self, prefix: &str) -> PrefixId
Add prefix.
If the prefix already exists, return its id.
Sourcepub fn no_namespace(&self) -> NamespaceId
pub fn no_namespace(&self) -> NamespaceId
No namespace
Returns the namespace id used when an element or attribute isn’t in any namespace.
Sourcepub fn empty_prefix(&self) -> PrefixId
pub fn empty_prefix(&self) -> PrefixId
Empty prefix
Returns the prefix id used when an element or attribute doesn’t have a prefix.
Sourcepub fn xml_prefix(&self) -> PrefixId
pub fn xml_prefix(&self) -> PrefixId
XML prefix
The prefix xml
used for the XML namespace.
Sourcepub fn xml_namespace(&self) -> NamespaceId
pub fn xml_namespace(&self) -> NamespaceId
XML namespace
Returns the namespace id used for the XML namespace.
Also known as http://wwww.w3.org/XML/1998/namespace
Sourcepub fn xml_space_name(&self) -> NameId
pub fn xml_space_name(&self) -> NameId
xml:space
Returns the name id used for the xml:space
attribute.
Sourcepub fn xml_id_name(&self) -> NameId
pub fn xml_id_name(&self) -> NameId
xml:id
Returns the name id used for the xml:id
attribute.
Sourcepub fn name_ref(
&self,
name_id: NameId,
context: Node,
) -> Result<RefName<'_>, Error>
pub fn name_ref( &self, name_id: NameId, context: Node, ) -> Result<RefName<'_>, Error>
Given a name id, and a context node (to provide namespace prefix
lookup), return a xmlname::RefName
. If you import the trait
xmlname::NameStrInfo
you can look up more information about the
name.
use xot::Xot;
use xot::xmlname::NameStrInfo;
let mut xot = Xot::new();
let root = xot.parse(r#"<ex:doc xmlns:ex="http://example.com"><a/></ex:doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let doc_name = xot.name_ref(xot.node_name(doc_el).unwrap(), a_el)?;
assert_eq!(doc_name.local_name(), "doc");
assert_eq!(doc_name.namespace(), "http://example.com");
assert_eq!(doc_name.prefix(), "ex");
assert_eq!(doc_name.full_name(), "ex:doc");
let a_name = xot.name_ref(xot.node_name(a_el).unwrap(), a_el)?;
assert_eq!(a_name.local_name(), "a");
assert_eq!(a_name.namespace(), "");
assert_eq!(a_name.prefix(), "");
assert_eq!(a_name.full_name(), "a");
Sourcepub fn name_ns_str(&self, name: NameId) -> (&str, &str)
pub fn name_ns_str(&self, name: NameId) -> (&str, &str)
Look up localname, namespace uri for name id
If this name id is not in a namespace, the namespace uri is the empty string.
No namespace:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a/></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let a_value = xot.element(a_el).unwrap();
let (localname, namespace) = xot.name_ns_str(a_value.name());
assert_eq!(localname, "a");
assert_eq!(namespace, "");
With namespace:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc xmlns="http://example.com"><a/></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let a_value = xot.element(a_el).unwrap();
let (localname, namespace) = xot.name_ns_str(a_value.name());
assert_eq!(localname, "a");
assert_eq!(namespace, "http://example.com");
Sourcepub fn local_name_str(&self, name: NameId) -> &str
pub fn local_name_str(&self, name: NameId) -> &str
Get the localname of a name.
Sourcepub fn namespace_str(&self, namespace: NamespaceId) -> &str
pub fn namespace_str(&self, namespace: NamespaceId) -> &str
Look up namespace uri for namespace id
An empty string slice indicates the no namespace.
Sourcepub fn prefix_str(&self, prefix: PrefixId) -> &str
pub fn prefix_str(&self, prefix: PrefixId) -> &str
Look up string slice for prefix id
If the prefix id is the empty prefix, the string slice is the empty string.
Sourcepub fn namespace_for_name(&self, name: NameId) -> NamespaceId
pub fn namespace_for_name(&self, name: NameId) -> NamespaceId
Get the Namespace for a Name
use xot::Xot;
let mut xot = Xot::new();
let ns = xot.add_namespace("http://example.com");
let name = xot.add_name_ns("a", ns);
assert_eq!(xot.namespace_for_name(name), ns);
Sourcepub fn full_name(&self, node: Node, name: NameId) -> Result<String, Error>
pub fn full_name(&self, node: Node, name: NameId) -> Result<String, Error>
Full name.
Given a context node, determine the full name string of the given name.
If the name doesn’t have a namespace, that’s identical to the localname. If the name is in a namespace, a prefix is looked up. If no prefix exists, that’s an error.
use xot::Xot;
// prefixed
let mut xot = Xot::new();
let doc = xot.parse(r#"<foo:doc xmlns:foo="http://example.com"/>"#)?;
let doc_el = xot.document_element(doc).unwrap();
let name = xot.node_name(doc_el).unwrap();
let full_name = xot.full_name(doc_el, name)?;
let full_name = xot.full_name(doc_el, name)?;
assert_eq!(full_name, "foo:doc");
// default namespace
let doc = xot.parse(r#"<doc xmlns="http://example.com"/>"#)?;
let doc_el = xot.document_element(doc).unwrap();
let name = xot.node_name(doc_el).unwrap();
let full_name = xot.full_name(doc_el, name)?;
assert_eq!(full_name, "doc");
// no namespace
let doc = xot.parse(r#"<doc/>"#)?;
let doc_el = xot.document_element(doc).unwrap();
let name = xot.node_name(doc_el).unwrap();
let full_name = xot.full_name(doc_el, name)?;
assert_eq!(full_name, "doc");
Sourcepub fn node_name(&self, node: Node) -> Option<NameId>
pub fn node_name(&self, node: Node) -> Option<NameId>
Given a node, give back the name id of this node.
For elements and attribute that is their name, for processing instructions this is a name based on the target attribute.
For anything else, it’s None
.
Sourcepub fn node_name_ref(&self, node: Node) -> Result<Option<RefName<'_>>, Error>
pub fn node_name_ref(&self, node: Node) -> Result<Option<RefName<'_>>, Error>
Given a node, give back the xmlname::RefName
of this node.
For elements and attribute that is their name, for processing instructions this is a name based on the target attribute.
For anything else, it’s None
.
use xot::Xot;
use xot::xmlname::NameStrInfo;
let mut xot = Xot::new();
let root = xot.parse(r#"<ex:doc xmlns:ex="http://example.com" ex:b="B"><a/></ex:doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let doc_name = xot.node_name_ref(doc_el)?.unwrap();
assert_eq!(doc_name.local_name(), "doc");
assert_eq!(doc_name.namespace(), "http://example.com");
assert_eq!(doc_name.prefix(), "ex");
assert_eq!(doc_name.full_name(), "ex:doc");
let a_name = xot.node_name_ref(a_el)?.unwrap();
assert_eq!(a_name.local_name(), "a");
assert_eq!(a_name.namespace(), "");
assert_eq!(a_name.prefix(), "");
assert_eq!(a_name.full_name(), "a");
// it also works on attribute nodes
let b_attribute = xot.attributes(doc_el).nodes().next().unwrap();
let b_name = xot.node_name_ref(b_attribute)?.unwrap();
assert_eq!(b_name.local_name(), "b");
assert_eq!(b_name.namespace(), "http://example.com");
assert_eq!(b_name.prefix(), "ex");
assert_eq!(b_name.full_name(), "ex:b");
Sourcepub fn is_prefix_defined(&self, node: Node, prefix: PrefixId) -> bool
pub fn is_prefix_defined(&self, node: Node, prefix: PrefixId) -> bool
Check whether a prefix is defined in node or its ancestors.
Sourcepub fn inherited_prefixes(&self, node: Node) -> Prefixes
pub fn inherited_prefixes(&self, node: Node) -> Prefixes
Find prefixes we inherit from ancestors and aren’t defined locally
Sourcepub fn prefix_for_namespace(
&self,
node: Node,
namespace: NamespaceId,
) -> Option<PrefixId>
pub fn prefix_for_namespace( &self, node: Node, namespace: NamespaceId, ) -> Option<PrefixId>
Find prefix for a namespace in node or ancestors.
Returns None
if no prefix is defined for the namespace.
Sourcepub fn namespace_for_prefix(
&self,
node: Node,
prefix: PrefixId,
) -> Option<NamespaceId>
pub fn namespace_for_prefix( &self, node: Node, prefix: PrefixId, ) -> Option<NamespaceId>
Find namespace for prefix in node or ancestors.
Return None
if no namespace is defined for the prefix.
Sourcepub fn create_missing_prefixes(&mut self, node: Node) -> Result<(), Error>
pub fn create_missing_prefixes(&mut self, node: Node) -> Result<(), Error>
Creating missing prefixes.
Due to creation or moving subtrees you can end up with XML elements or attributes that have names in a namespace without a prefix to define the namespace in its ancestors.
This function creates the missing prefixes on the given node. The prefixes are named “n0”, “n1”, “n2”, etc.
You can use this function just before serializing the tree to XML
using Xot::write
or Xot::to_string
.
Sourcepub fn deduplicate_namespaces(&mut self, node: Node)
pub fn deduplicate_namespaces(&mut self, node: Node)
Deduplicate namespaces.
Any namespace definition lower down that defines a prefix for a namespace that is already known in an ancestor is removed.
There is a special rule for attributes, as they can only be in a namespace if they have an explicit prefix; the prefix is not removed if it overlaps with a default namespace.
With default namespaces:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc xmlns="http://example.com"><a xmlns="http://example.com"/></doc>"#)?;
xot.deduplicate_namespaces(root);
assert_eq!(xot.to_string(root)?, r#"<doc xmlns="http://example.com"><a/></doc>"#);
With explicit prefixes:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<ns:doc xmlns:ns="http://example.com"><ns:a xmlns:ns="http://example.com"/></ns:doc>"#)?;
xot.deduplicate_namespaces(root);
assert_eq!(xot.to_string(root)?, r#"<ns:doc xmlns:ns="http://example.com"><ns:a/></ns:doc>"#);
This also works if you use different prefixes for the same namespace URI:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<ns:doc xmlns:ns="http://example.com"><other:a xmlns:other="http://example.com"/></ns:doc>"#)?;
xot.deduplicate_namespaces(root);
assert_eq!(xot.to_string(root)?, r#"<ns:doc xmlns:ns="http://example.com"><ns:a/></ns:doc>"#);
Sourcepub fn unresolved_namespaces(&self, node: Node) -> Vec<NamespaceId>
pub fn unresolved_namespaces(&self, node: Node) -> Vec<NamespaceId>
Get namespaces without prefix within node or its descendants.
Any elements or attribute with namespaces that don’t have a prefix defined for them in the context of the node are reported.
Sourcepub fn namespaces_in_scope(
&self,
node: Node,
) -> impl Iterator<Item = (PrefixId, NamespaceId)> + '_
pub fn namespaces_in_scope( &self, node: Node, ) -> impl Iterator<Item = (PrefixId, NamespaceId)> + '_
Returns an iterator that yields all the prefix/namespace combinations.
Once a prefix has been yielded, it’s not yielded again, as the overriding prefix has already been yielded.
Source§impl Xot
§Parsing
impl Xot
§Parsing
Sourcepub fn parse_with_span_info(
&mut self,
xml: &str,
) -> Result<(Node, SpanInfo), ParseError>
pub fn parse_with_span_info( &mut self, xml: &str, ) -> Result<(Node, SpanInfo), ParseError>
Parse a string containing XML into a document node. Retain span information.
This parses the XML source into a Xot tree, and also returns
SpanInfo
which describes where nodes in the
tree are located in the source text.
Sourcepub fn parse_fragment_with_span_info(
&mut self,
xml: &str,
) -> Result<(Node, SpanInfo), ParseError>
pub fn parse_fragment_with_span_info( &mut self, xml: &str, ) -> Result<(Node, SpanInfo), ParseError>
Parse a string containing an XML fragment into a document node.
This is similar to `Xot::parse``, but it relaxes the well-formedness requirements. Specifically, it allows text nodes at the top level, and does not require a document element, and allows multiple elements. In short, a fragment behaves like an element (without name, attributes or namespace definitions).
This is to support https://www.w3.org/TR/xpath-datamodel/#DocumentNode which is more permissive than standard XML.
This parses the XML source into a Xot tree, and also returns
SpanInfo
which describes where nodes in the
tree are located in the source text.
Sourcepub fn parse(&mut self, xml: &str) -> Result<Node, ParseError>
pub fn parse(&mut self, xml: &str) -> Result<Node, ParseError>
Parse a string containing XML into a document node.
Even though the encoding in the XML declaration may indicate otherwise,
the string is interpreted as a Rust string, i.e. UTF-8. If you need to
decode the string first, use Xot::parse_bytes
.
The returned node is the document node of the parsed XML document.
use xot::Xot;
let mut xot = Xot::new();
let document = xot.parse("<hello/>")?;
Sourcepub fn parse_fragment(&mut self, xml: &str) -> Result<Node, ParseError>
pub fn parse_fragment(&mut self, xml: &str) -> Result<Node, ParseError>
Parse a string containing an XML fragment into a document node.
This is similar to `Xot::parse``, but it relaxes the well-formedness requirements. Specifically, it allows text nodes at the top level, and does not require a document element, and allows multiple elements. In short, a fragment behaves like an element (without name, attributes or namespace definitions).
This is to support https://www.w3.org/TR/xpath-datamodel/#DocumentNode which is more permissive than standard XML.
Sourcepub fn parse_bytes(&mut self, bytes: &[u8]) -> Result<Node, ParseError>
pub fn parse_bytes(&mut self, bytes: &[u8]) -> Result<Node, ParseError>
Parse bytes containing XML into a node.
This attempts to decode the data in the bytes into a Rust string (UTF-8) first, then parses this string.
If you already have a Rust string, use Xot::parse
.
The returned node is the document node of the parsed XML document.
use xot::Xot;
let mut xot = Xot::new();
let document = xot.parse_bytes(b"<hello/>")?;
use xot::Xot;
let mut xot = Xot::new();
let document = xot.parse_bytes(b"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><p>\xe9</p>").unwrap();
let doc_el = xot.document_element(document)?;
let txt_value = xot.text_content_str(doc_el).unwrap();
assert_eq!(txt_value, "é");
Source§impl Xot
§Serialization
impl Xot
§Serialization
Sourcepub fn write(&self, node: Node, w: &mut impl Write) -> Result<(), Error>
pub fn write(&self, node: Node, w: &mut impl Write) -> Result<(), Error>
Write node as XML.
This uses the default serialization parameters: no XML declaration, no doctype, no control over pretty printing or CDATA.
To serialize with this control use Xot::serialize_xml_write
.
If there are missing namespace prefixes, this errors. You can
automatically add missing prefixes by invoking
Xot::create_missing_prefixes
before serialization to avoid this
error.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<p>Example</p>")?;
let mut buf = Vec::new();
xot.write(root, &mut buf).unwrap();
assert_eq!(buf, b"<p>Example</p>");
Sourcepub fn to_string(&self, node: Node) -> Result<String, Error>
pub fn to_string(&self, node: Node) -> Result<String, Error>
Serialize node as XML string.
This uses the default serialization parameters: no XML declaration, no doctype, no control over pretty printing or CDATA.
To serialize with this control use Xot::serialize_xml_string
.
If there are missing namespace prefixes, this errors. You can automatically
add missing prefixes by invoking Xot::create_missing_prefixes
before
serialization to avoid this error.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<p>Example</p>")?;
let buf = xot.to_string(root)?;
assert_eq!(buf, "<p>Example</p>");
Sourcepub fn serialize_xml_string(
&self,
parameters: Parameters,
node: Node,
) -> Result<String, Error>
pub fn serialize_xml_string( &self, parameters: Parameters, node: Node, ) -> Result<String, Error>
Serialize to XML, with options.
Note that if you don’t need string output and have a writer available,
a more efficient option is to use Xot::serialize_xml_write
.
If there are missing namespace prefixes, this errors. You can automatically
add missing prefixes by invoking Xot::create_missing_prefixes
before
serialization to avoid this error.
With the default parameters:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<a><b/></a>")?;
let xml = xot.serialize_xml_string(Default::default(), root)?;
assert_eq!(xml, "<a><b/></a>");
With an XML declaration:
use xot::{Xot, output};
let mut xot = Xot::new();
let root = xot.parse("<a><b/></a>")?;
let xml = xot.serialize_xml_string(output::xml::Parameters {
declaration: Some(Default::default()),
..Default::default()
}, root)?;
assert_eq!(xml, "<?xml version=\"1.0\"?>\n<a><b/></a>");
XML declaration with an encoding declaration (does not affect output encoding):
use xot::{Xot, output};
let mut xot = Xot::new();
let root = xot.parse("<a><b/></a>")?;
let xml = xot.serialize_xml_string(output::xml::Parameters {
declaration: Some(output::xml::Declaration {
encoding: Some("UTF-8".to_string()),
..Default::default()
}),
..Default::default()
}, root)?;
assert_eq!(xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<a><b/></a>");
Pretty print XML:
use xot::{Xot, output};
let mut xot = Xot::new();
let root = xot.parse("<a><b/></a>")?;
let xml = xot.serialize_xml_string(output::xml::Parameters {
indentation: Some(Default::default()),
..Default::default()
}, root)?;
assert_eq!(xml, "<a>\n <b/>\n</a>\n");
Sourcepub fn serialize_xml_string_with_normalizer<N: Normalizer>(
&self,
parameters: Parameters,
node: Node,
normalizer: N,
) -> Result<String, Error>
pub fn serialize_xml_string_with_normalizer<N: Normalizer>( &self, parameters: Parameters, node: Node, normalizer: N, ) -> Result<String, Error>
Serialize a string using a normalizer for any text and attribute values.
If you enable the icu
feature then support for icu normalizers
is provided.
You can pass in an icu normalizer like this:
use xot::{Xot, output};
use icu::normalizer::ComposingNormalizer;
let normalizer = ComposingNormalizer::new_nfc();
// example taken from https://www.unicode.org/reports/tr15/ figure 5, second example
let xml = "<doc>\u{1E0B}\u{0323}</doc>";
let mut xot = Xot::new();
let root = xot.parse(xml).unwrap();
let s = xot.serialize_xml_string_with_normalizer(output::xml::Parameters::default(), root, normalizer).unwrap();
assert_eq!(s, "<doc>\u{1E0D}\u{0307}</doc>");
Sourcepub fn serialize_xml_write(
&self,
parameters: Parameters,
node: Node,
w: &mut impl Write,
) -> Result<(), Error>
pub fn serialize_xml_write( &self, parameters: Parameters, node: Node, w: &mut impl Write, ) -> Result<(), Error>
Serialize to XML via a Write
, with options.
This is like Xot::serialize_xml_string
but writes to a Write
. This
is more efficient if you want to write directly to a file, for
instance, as no string needs to be created in memory.
Sourcepub fn serialize_xml_write_with_normalizer<N: Normalizer>(
&self,
parameters: Parameters,
node: Node,
w: &mut impl Write,
normalizer: N,
) -> Result<(), Error>
pub fn serialize_xml_write_with_normalizer<N: Normalizer>( &self, parameters: Parameters, node: Node, w: &mut impl Write, normalizer: N, ) -> Result<(), Error>
Write XML with a normalizer for text and attribute values.
See Xot::serialize_xml_string_with_normalizer
for more information.
Sourcepub fn html5(&mut self) -> Html5<'_>
pub fn html5(&mut self) -> Html5<'_>
Get HTML 5 serialization API.
This is a mutable calls as it needs to create a lot of new HTML names first.
If you need to generate multiple HTML 5 serializations, it’s slightly more efficient not to re-create this each time.
Sourcepub fn outputs(&self, node: Node) -> impl Iterator<Item = (Node, Output<'_>)>
pub fn outputs(&self, node: Node) -> impl Iterator<Item = (Node, Output<'_>)>
Serialize node into outputs.
This creates an iterator of (Node, Output)
tokens. These can then be
processed externally, for instance with a custom parser.
You can use Xot::parse_with_span_info
to get access to source span
information in a crate::SpanInfo
. This can be handy to display
parser error information (as long as you don’t mutate the Xot
document).
Why do the round-trip through Xot instead of using an XML parser like
xmlparser
, xml_rs
or quick_xml
, which will be more efficient? By
using Xot you can guarantee that the XML is well-formed, entities and
namespaces have been expanded, and you have access to Xot names using
familiar Xot APIs.
Sourcepub fn tokens<'a, N: Normalizer + 'a>(
&'a self,
node: Node,
parameters: TokenSerializeParameters,
normalizer: N,
) -> impl Iterator<Item = (Node, Output<'a>, OutputToken)> + 'a
pub fn tokens<'a, N: Normalizer + 'a>( &'a self, node: Node, parameters: TokenSerializeParameters, normalizer: N, ) -> impl Iterator<Item = (Node, Output<'a>, OutputToken)> + 'a
Serialize node into outputs and tokens.
This creates an iterator that represents the serialized XML. You can use this to write custom renderers that serialize the XML in a different way, for instance with inline styling.
In parameters
you can control the behavior of the serializer, for
instance by specifying elements that should be serialized as a CDATA
section.
You can also pass in a normalizer; if you don’t care about normalization, use
Sourcepub fn pretty_tokens<'a, N: Normalizer + 'a>(
&'a self,
node: Node,
parameters: TokenSerializeParameters,
suppress_elements: &'a [NameId],
normalizer: N,
) -> impl Iterator<Item = (Node, Output<'a>, PrettyOutputToken)> + 'a
pub fn pretty_tokens<'a, N: Normalizer + 'a>( &'a self, node: Node, parameters: TokenSerializeParameters, suppress_elements: &'a [NameId], normalizer: N, ) -> impl Iterator<Item = (Node, Output<'a>, PrettyOutputToken)> + 'a
Serialize node into outputs and pretty printed tokens.
This creates an iterator that represents the serialized XML. You can use this to write custom renderers that serialize the XML in a different way, for instance with inline styling.
In parameters
you can control the behavior of the serializer, for
instance by specifying elements that should be serialized as a CDATA
section.
You can also include a list of elements names that are excluded from indentation.
You can also pass in a normalizer; if you don’t care about normalization, use
Source§impl Xot
§Value and type access
impl Xot
§Value and type access
Sourcepub fn value(&self, node_id: Node) -> &Value
pub fn value(&self, node_id: Node) -> &Value
Access to the XML value for this node.
use xot::{Xot, Value};
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let doc_name = xot.name("doc").unwrap();
match xot.value(doc_el) {
Value::Element(element) => {
assert_eq!(element.name(), doc_name);
}
_ => { }
}
Note that if you already know the type of a node value or are
only interested in a single type, you can use the convenience
methods like Xot::element
.
Sourcepub fn value_mut(&mut self, node_id: Node) -> &mut Value
pub fn value_mut(&mut self, node_id: Node) -> &mut Value
Mutable access to the XML value for this node.
use xot::{Xot, Value};
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
match xot.value_mut(doc_el) {
Value::Text(text) => {
text.set("Changed");
}
_ => { }
}
Note that if you already know the type of a node value or are
only interested in a single type, you can use the convenience
methods like Xot::text_mut
Sourcepub fn value_type(&self, node: Node) -> ValueType
pub fn value_type(&self, node: Node) -> ValueType
Get the ValueType
of a node.
Sourcepub fn has_document_parent(&self, node: Node) -> bool
pub fn has_document_parent(&self, node: Node) -> bool
Return true if node is directly under the document node. This means it’s either the document element or a comment or processing instruction.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert!(xot.has_document_parent(doc_el));
assert!(!xot.has_document_parent(text_node));
Sourcepub fn is_document_element(&self, node: Node) -> bool
pub fn is_document_element(&self, node: Node) -> bool
Return true if the node is the document element.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert!(xot.is_document_element(doc_el));
assert!(!xot.is_document_element(text_node));
Sourcepub fn is_document(&self, node: Node) -> bool
pub fn is_document(&self, node: Node) -> bool
Return true if node is the document node.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
assert!(xot.is_document(root));
assert!(!xot.is_document(doc_el));
Sourcepub fn is_element(&self, node: Node) -> bool
pub fn is_element(&self, node: Node) -> bool
Return true if node is an element.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert!(xot.is_element(doc_el));
assert!(!xot.is_element(text_node));
Sourcepub fn is_text(&self, node: Node) -> bool
pub fn is_text(&self, node: Node) -> bool
Return true if node is text.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert!(xot.is_text(text_node));
assert!(!xot.is_text(doc_el));
Sourcepub fn is_comment(&self, node: Node) -> bool
pub fn is_comment(&self, node: Node) -> bool
Return true if node is a comment.
Sourcepub fn is_processing_instruction(&self, node: Node) -> bool
pub fn is_processing_instruction(&self, node: Node) -> bool
Return true if node is a processing instruction.
Sourcepub fn is_namespace_node(&self, node: Node) -> bool
pub fn is_namespace_node(&self, node: Node) -> bool
Return true if node is a namespace node.
Sourcepub fn is_attribute_node(&self, node: Node) -> bool
pub fn is_attribute_node(&self, node: Node) -> bool
Return true if node is an attribute node.
Sourcepub fn text(&self, node: Node) -> Option<&Text>
pub fn text(&self, node: Node) -> Option<&Text>
If this node’s value is text, return a reference to it.
Note that Xot::text_str()
is a more convenient way to
get the text value as a string slice.
See also Xot::text_mut()
if you want to manipulate
a text value.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert_eq!(xot.text(text_node).unwrap().get(), "Example");
assert!(xot.text(doc_el).is_none());
Sourcepub fn text_str(&self, node: Node) -> Option<&str>
pub fn text_str(&self, node: Node) -> Option<&str>
If this node’s value is text, return a reference to the string.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root).unwrap();
let text_node = xot.first_child(doc_el).unwrap();
assert_eq!(xot.text_str(text_node).unwrap(), "Example");
assert!(xot.text_str(doc_el).is_none());
Sourcepub fn text_mut(&mut self, node: Node) -> Option<&mut Text>
pub fn text_mut(&mut self, node: Node) -> Option<&mut Text>
If this node’s value is a text, return a mutable reference to it.
This can be used to manipulate the text content of a document.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc>Example</doc>")?;
let doc_el = xot.document_element(root)?;
let text_node = xot.first_child(doc_el).unwrap();
let text = xot.text_mut(text_node).unwrap();
text.set("New text");
assert_eq!(xot.text_str(text_node).unwrap(), "New text");
assert_eq!(xot.to_string(root)?, "<doc>New text</doc>");
Sourcepub fn get_element_name(&self, node: Node) -> NameId
pub fn get_element_name(&self, node: Node) -> NameId
Get the name of a node that’s an element.
If the node does not exist, then panic.
Sourcepub fn element(&self, node: Node) -> Option<&Element>
pub fn element(&self, node: Node) -> Option<&Element>
If this node’s value is an element, return a reference to it.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><child a="A"/></doc>"#)?;
let doc_el = xot.document_element(root).unwrap();
let child_el = xot.first_child(doc_el).unwrap();
let element = xot.element(child_el).unwrap();
let child_name = xot.name("child").unwrap();
assert_eq!(element.name(), child_name);
Sourcepub fn element_mut(&mut self, node: Node) -> Option<&mut Element>
pub fn element_mut(&mut self, node: Node) -> Option<&mut Element>
If this node’s value is an element, return a mutable reference to it.
You can use this to change an element’s name.
use xot::Xot;
let mut xot = Xot::new();
let changed = xot.add_name("changed");
let root = xot.parse(r#"<doc><child/></doc>"#)?;
let doc_el = xot.document_element(root)?;
let child_el = xot.first_child(doc_el).unwrap();
let element = xot.element_mut(child_el).unwrap();
element.set_name(changed);
assert_eq!(xot.to_string(root)?, r#"<doc><changed/></doc>"#);
Sourcepub fn text_content(&self, node: Node) -> Option<&Text>
pub fn text_content(&self, node: Node) -> Option<&Text>
If this element has only a single text child, return a reference to it.
If the element has no children or more than one child, return None
.
Note that Xot::text_content_str()
is a more convenient way to get
the text value as a string slice.
See also Xot::text_content_mut()
if you want to manipulate a text value.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc><a>Example</a><b/></doc>")?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let b_el = xot.next_sibling(a_el).unwrap();
let text = xot.text_content(a_el).unwrap();
assert_eq!(text.get(), "Example");
assert!(xot.text_content(b_el).is_none());
Sourcepub fn text_content_mut(&mut self, node: Node) -> Option<&mut Text>
pub fn text_content_mut(&mut self, node: Node) -> Option<&mut Text>
If this element has only a single text child, return a mutable reference to it.
If the element has no children, create a text child and return multiple reference to its value.
If the element more than one child, return None
.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc><a>Example</a><b/></doc>")?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let b_el = xot.next_sibling(a_el).unwrap();
let text = xot.text_content_mut(a_el).unwrap();
text.set("New value");
assert_eq!(xot.to_string(root)?, "<doc><a>New value</a><b/></doc>");
let text = xot.text_content_mut(b_el).unwrap();
text.set("New value 2");
assert_eq!(xot.to_string(root)?, "<doc><a>New value</a><b>New value 2</b></doc>");
Sourcepub fn text_content_str(&self, node: Node) -> Option<&str>
pub fn text_content_str(&self, node: Node) -> Option<&str>
If this element only has a single text child, return str reference to it.
If the element has no content, return Some("")
.
If the element has more than one child, return None
.
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse("<doc><a>Example</a><b/><c><x/></c></doc>")?;
let doc_el = xot.document_element(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let b_el = xot.next_sibling(a_el).unwrap();
let c_el = xot.next_sibling(b_el).unwrap();
let text = xot.text_content_str(a_el).unwrap();
assert_eq!(text, "Example");
let text = xot.text_content_str(b_el).unwrap();
assert_eq!(text, "");
assert!(xot.text_content_str(c_el).is_none());
Sourcepub fn comment(&self, node: Node) -> Option<&Comment>
pub fn comment(&self, node: Node) -> Option<&Comment>
If this node’s value is a comment, return a reference to it.
Sourcepub fn comment_str(&self, node: Node) -> Option<&str>
pub fn comment_str(&self, node: Node) -> Option<&str>
If this node’s value is a comment, return a reference to the string.
Sourcepub fn comment_mut(&mut self, node: Node) -> Option<&mut Comment>
pub fn comment_mut(&mut self, node: Node) -> Option<&mut Comment>
If this node’s value is a comment, return a mutable reference to it.
Sourcepub fn processing_instruction(
&self,
node: Node,
) -> Option<&ProcessingInstruction>
pub fn processing_instruction( &self, node: Node, ) -> Option<&ProcessingInstruction>
If this node’s value is a processing instruction, return a reference to it.
Sourcepub fn processing_instruction_mut(
&mut self,
node: Node,
) -> Option<&mut ProcessingInstruction>
pub fn processing_instruction_mut( &mut self, node: Node, ) -> Option<&mut ProcessingInstruction>
If this node’s value is a processing instruction, return a mutable reference to it.
Sourcepub fn namespace_node(&self, node: Node) -> Option<&Namespace>
pub fn namespace_node(&self, node: Node) -> Option<&Namespace>
Access namespace node value
Sourcepub fn namespace_node_mut(&mut self, node: Node) -> Option<&mut Namespace>
pub fn namespace_node_mut(&mut self, node: Node) -> Option<&mut Namespace>
Manipulate namespace node value
Sourcepub fn attribute_node(&self, node: Node) -> Option<&Attribute>
pub fn attribute_node(&self, node: Node) -> Option<&Attribute>
Access attribute node value
Sourcepub fn attribute_node_mut(&mut self, node: Node) -> Option<&mut Attribute>
pub fn attribute_node_mut(&mut self, node: Node) -> Option<&mut Attribute>
Manipulate attribute node value
Sourcepub fn string_value(&self, node: Node) -> String
pub fn string_value(&self, node: Node) -> String
Given a node, give back a string representation.
For the root node and element nodes this gives back all text node descendant content, concatenated.
For text nodes, it gives back the text.
For comments, it gives back the comment text.
For processing instructions, it gives back their content (data).
For attribute nodes, it gives back the attribute value.
For namespace nodes, it gives back the namespace URI.
This is defined by the string-value
property in
https://www.w3.org/TR/xpath-datamodel-31
Sourcepub fn deep_equal(&self, a: Node, b: Node) -> bool
pub fn deep_equal(&self, a: Node, b: Node) -> bool
Check two nodes for semantic equality.
This is a deep comparison of the nodes and their children. The trees have to have the same structure.
A name is considered to be semantically equal to another name if they have the same namespace and local name. Prefixes are ignored.
Two elements are the same if their name and attributes are the same. Namespace declarations are ignored.
Text nodes, comments and processing instructions are considered to be the same if their values are the same.
Compare two documents:
use xot::Xot;
let mut xot = Xot::new();
let root0 = xot.parse("<doc><a>Example</a><b/></doc>")?;
let root1 = xot.parse("<doc><a>Example</a><b/></doc>")?;
assert!(xot.deep_equal(root0, root1));
Different prefixes are ignored; the namespace URI is what is compared:
use xot::Xot;
let mut xot = Xot::new();
let root0 = xot.parse("<doc xmlns:foo='http://example.com'><foo:a/></doc>")?;
let root1 = xot.parse("<doc xmlns:bar='http://example.com'><bar:a/></doc>")?;
assert!(xot.deep_equal(root0, root1));
But different text is a real difference:
use xot::Xot;
let mut xot = Xot::new();
let root0 = xot.parse("<doc>Example</doc>")?;
let root1 = xot.parse("<doc>Changed</doc>")?;
assert!(!xot.deep_equal(root0, root1));
You can compare any nodes, not just documents:
use xot::Xot;
let mut xot = Xot::new();
let root = xot.parse(r#"<doc><a f="F"/><b/><a f="F"/></doc>"#)?;
let doc_el = xot.first_child(root).unwrap();
let a_el = xot.first_child(doc_el).unwrap();
let b_el = xot.next_sibling(a_el).unwrap();
let a2_el = xot.next_sibling(b_el).unwrap();
assert!(xot.deep_equal(a_el, a2_el));
assert!(!xot.deep_equal(a_el, b_el));
Sourcepub fn deep_equal_children(&self, a: Node, b: Node) -> bool
pub fn deep_equal_children(&self, a: Node, b: Node) -> bool
Compare the children of two nodes
If the children are the same semantically, return true. It ignores
the name and attributes of the a
and b
nodes themselves.
Sourcepub fn deep_equal_xpath(
&self,
a: Node,
b: Node,
text_compare: impl Fn(&str, &str) -> bool,
) -> bool
pub fn deep_equal_xpath( &self, a: Node, b: Node, text_compare: impl Fn(&str, &str) -> bool, ) -> bool
XPath deep equal Comparison of two nodes as defined by the XPath deep-equal function:
https://www.w3.org/TR/xpath-functions-31/#func-deep-equal
We ignore anything about typed content in that definition.
Sourcepub fn advanced_deep_equal<F, C>(
&self,
a: Node,
b: Node,
filter: F,
text_compare: C,
) -> bool
pub fn advanced_deep_equal<F, C>( &self, a: Node, b: Node, filter: F, text_compare: C, ) -> bool
Compare two nodes for semantic equality with custom text compare and filtering.
This is a deep comparison of the nodes and their children. The trees have to have the same structure.
A name is considered to be semantically equal to another name if they have the same namespace and local name. Prefixes are ignored.
Two elements are the same if their name and attributes are the same. Namespace declarations are ignored.
You can include only the nodes that are relevant to the comparison using the filter function.
Text nodes and attributes are compared using the provided comparison function.
Sourcepub fn shallow_equal(&self, a: Node, b: Node) -> bool
pub fn shallow_equal(&self, a: Node, b: Node) -> bool
Shallow compare two nodes.
Does not consider content of any nodes, but does compare attributes.
Sourcepub fn shallow_equal_ignore_attributes(
&self,
a: Node,
b: Node,
ignore_attributes: &[NameId],
) -> bool
pub fn shallow_equal_ignore_attributes( &self, a: Node, b: Node, ignore_attributes: &[NameId], ) -> bool
Shallow compare two nodes, with possibility to ignore attributes.
Attributes of elements are compared, except those listed to ignore.
Child content of the root or elements is not considered.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Xot
impl RefUnwindSafe for Xot
impl Send for Xot
impl Sync for Xot
impl Unpin for Xot
impl UnwindSafe for Xot
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more