use std::fmt;
use markup5ever::{QualName, Namespace as Ns, LocalName};
use crate::{Evaluation, Nodeset, Node as DomNode};
pub trait NodeTest: fmt::Debug {
fn test(&self, context: &Evaluation, result: &mut Nodeset);
}
#[derive(Debug, Clone, PartialEq)]
pub struct NameTest { pub prefix: Option<String>,
pub local_part: String
}
impl NameTest {
fn is_match(&self, _context: &Evaluation, qname: &QualName) -> bool {
let has_wildcard = self.local_part == "*";
if has_wildcard {
true
} else {
self.local_part.as_str() == &qname.local
}
}
}
#[derive(Debug)]
pub struct Attribute {
name_test: NameTest,
}
impl Attribute {
pub fn new(name: NameTest) -> Attribute {
Attribute { name_test: name }
}
}
impl NodeTest for Attribute {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if context.node.is_attribute() {
if let Some(attr) = context.node.attribute() {
if self.name_test.is_match(context, &attr.attr.name) {
result.add_node(context.node.clone());
}
}
}
}
}
#[derive(Debug)]
pub struct Namespace {
name_test: NameTest,
}
impl Namespace {
pub fn new(name_test: NameTest) -> Namespace {
Namespace { name_test }
}
}
impl NodeTest for Namespace {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if context.node.is_namespace() && self.name_test.is_match(context, &QualName::new(None, Ns::from(""), LocalName::from(context.node.prefix()))) {
result.add_node(context.node.clone());
}
}
}
#[derive(Debug)]
pub struct Element {
name_test: NameTest,
}
impl Element {
pub fn new(name_test: NameTest) -> Element {
Element { name_test }
}
}
impl NodeTest for Element {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if let Some(name) = context.node.name() {
if context.node.is_element() && self.name_test.is_match(context, &name) {
result.add_node(context.node.clone());
}
}
}
}
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Node;
impl NodeTest for Node {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
result.add_node(context.node.clone());
}
}
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Text;
impl NodeTest for Text {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if let DomNode::Text(_) = context.node {
result.add_node(context.node.clone());
}
}
}
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Comment;
impl NodeTest for Comment {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if let DomNode::Comment(_) = context.node {
result.add_node(context.node.clone());
}
}
}
#[derive(Debug)]
pub struct ProcessingInstruction {
target: Option<String>,
}
impl ProcessingInstruction {
pub fn new(target: Option<String>) -> ProcessingInstruction {
ProcessingInstruction { target }
}
}
impl NodeTest for ProcessingInstruction {
fn test(&self, context: &Evaluation, result: &mut Nodeset) {
if context.node.is_processing_instruction() {
match (self.target.as_deref(), context.node.target()) {
(Some(name), Some(ref context_target)) if name == context_target => result.add_node(context.node.clone()),
(None, _) => result.add_node(context.node.clone()),
_ => {}
}
}
}
}