nom_xml/
processing_instruction.rs1use crate::{parse::Parse, IResult, Name};
4use nom::{
5 bytes::complete::tag,
6 combinator::{map, map_res, opt, peek},
7 multi::many_till,
8 sequence::{preceded, tuple},
9};
10
11#[derive(Clone, PartialEq, Eq)]
12pub struct ProcessingInstruction {
13 pub target: Name,
14 pub data: Option<String>,
15}
16
17impl<'a> Parse<'a> for ProcessingInstruction {
18 type Args = ();
19 type Output = IResult<&'a str, Self>;
20
21 fn parse(input: &'a str, _args: Self::Args) -> Self::Output {
23 map(
24 tuple((
25 tag("<?"),
26 Self::parse_target,
27 opt(preceded(
28 Self::parse_multispace1,
29 many_till(Self::parse_char, peek(tag("?>"))),
30 )),
31 tag("?>"),
32 )),
33 |(_open_tag, target, data_chars_opt, _close_tag)| {
34 let data = data_chars_opt.map(|(chars, _)| chars.into_iter().collect::<String>());
35 ProcessingInstruction { target, data }
36 },
37 )(input)
38 }
39}
40
41impl ProcessingInstruction {
42 fn parse_target(input: &str) -> IResult<&str, Name> {
44 map_res(Self::parse_name, |name| {
45 if name.local_part.eq_ignore_ascii_case("xml") {
46 Err(nom::Err::Failure(nom::error::Error::new(
47 input,
48 nom::error::ErrorKind::Tag,
49 )))
50 } else {
51 Ok(name)
52 }
53 })(input)
54 }
55}