nom_xml/
namespaces.rs

1use crate::{error::Error, parse::Parse, IResult, Name};
2use nom::{
3    branch::alt,
4    bytes::complete::tag,
5    character::complete::{anychar, char},
6    combinator::{map, verify},
7    sequence::{pair, preceded, tuple},
8};
9
10pub trait ParseNamespace<'a>: Parse<'a> + Sized {
11    // [1] NSAttName ::=   	PrefixedAttName | DefaultAttName
12    fn parse_namespace_attribute_name(input: &str) -> IResult<&str, Name> {
13        let (input, name) = alt((Self::parse_name, Self::parse_prefixed_attribute_name))(input)?;
14        if name.prefix.is_none() && name.local_part != "xmlns" {
15            return Err(nom::Err::Error(Error::NomError(nom::error::Error::new(
16                input.into(),
17                nom::error::ErrorKind::Verify,
18            ))));
19        }
20
21        Ok((input, name))
22    }
23
24    // [2] PrefixedAttName ::=  'xmlns:' NCName
25    fn parse_prefixed_attribute_name(input: &str) -> IResult<&str, Name> {
26        map(
27            preceded(tag("xmlns:"), Self::parse_non_colonized_name),
28            |local_part| Name {
29                prefix: Some("xmlns".into()),
30                local_part,
31            },
32        )(input)
33    }
34
35    // [4] NCName ::= Name - (Char* ':' Char*)  /* An XML Name, minus the ":" */
36    fn parse_non_colonized_name(input: &str) -> IResult<&str, String> {
37        map(
38            pair(
39                Self::parse_name_start_char,
40                nom::bytes::complete::take_while1(|c: char| Self::is_name_char(c) && c != ':'),
41            ),
42            |(start_char, rest_chars)| {
43                let mut name = start_char.to_string();
44                name.push_str(rest_chars);
45                name
46            },
47        )(input)
48    }
49
50    // [5] NCNameChar ::= NameChar - ':' /* An XML NameChar, minus the ":" */
51    fn parse_non_colonized_name_char(input: &str) -> IResult<&str, char> {
52        verify(Self::parse_name_char, |c| *c != ':')(input)
53    }
54
55    // [6] NCNameStartChar ::= NCName - ( Char Char Char* ) /* The first letter of an NCName */
56    fn parse_non_colonized_name_start_char(input: &str) -> IResult<&str, char> {
57        verify(anychar, |c| *c != ':')(input)
58    }
59
60    // [7] QName ::= PrefixedName | UnprefixedName
61    fn parse_qualified_name(input: &str) -> IResult<&str, Name> {
62        alt((
63            Self::parse_prefixed_name,
64            map(Self::parse_non_colonized_name, |local_part| Name {
65                prefix: None,
66                local_part,
67            }),
68            Self::parse_name, //unprefixed name
69        ))(input)
70    }
71
72    // [8] PrefixedName	::= Prefix ':' LocalPart
73    fn parse_prefixed_name(input: &str) -> IResult<&str, Name> {
74        map(
75            tuple((
76                Self::parse_non_colonized_name,
77                char(':'),
78                Self::parse_non_colonized_name,
79            )),
80            |(prefix, _colon_literal, local_part)| Name {
81                prefix: Some(prefix),
82                local_part,
83            },
84        )(input)
85    }
86
87    // [9] UnprefixedName ::= LocalPart
88    // [10] Prefix ::= NCName
89    // [11] LocalPart ::= NCName
90}