xml/reader/parser/
inside_opening_tag.rs

1use common::is_name_start_char;
2use attribute::OwnedAttribute;
3use namespace;
4
5use reader::lexer::Token;
6
7use super::{Result, PullParser, State, OpeningTagSubstate, QualifiedNameTarget};
8
9impl PullParser {
10    pub fn inside_opening_tag(&mut self, t: Token, s: OpeningTagSubstate) -> Option<Result> {
11        macro_rules! unexpected_token(($t:expr) => (Some(self_error!(self; "Unexpected token inside opening tag: {}", $t))));
12        match s {
13            OpeningTagSubstate::InsideName => self.read_qualified_name(t, QualifiedNameTarget::OpeningTagNameTarget, |this, token, name| {
14                match name.prefix_ref() {
15                    Some(prefix) if prefix == namespace::NS_XML_PREFIX ||
16                                    prefix == namespace::NS_XMLNS_PREFIX =>
17                        Some(self_error!(this; "'{:?}' cannot be an element name prefix", name.prefix)),
18                    _ => {
19                        this.data.element_name = Some(name.clone());
20                        match token {
21                            Token::TagEnd => this.emit_start_element(false),
22                            Token::EmptyTagEnd => this.emit_start_element(true),
23                            Token::Whitespace(_) => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag)),
24                            _ => unreachable!()
25                        }
26                    }
27                }
28            }),
29
30            OpeningTagSubstate::InsideTag => match t {
31                Token::Whitespace(_) => None,  // skip whitespace
32                Token::Character(c) if is_name_start_char(c) => {
33                    self.buf.push(c);
34                    self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeName))
35                }
36                Token::TagEnd => self.emit_start_element(false),
37                Token::EmptyTagEnd => self.emit_start_element(true),
38                _ => unexpected_token!(t)
39            },
40
41            OpeningTagSubstate::InsideAttributeName => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
42                this.data.attr_name = Some(name);
43                match token {
44                    Token::Whitespace(_) => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeName)),
45                    Token::EqualsSign => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeValue)),
46                    _ => unreachable!()
47                }
48            }),
49
50            OpeningTagSubstate::AfterAttributeName => match t {
51                Token::Whitespace(_) => None,
52                Token::EqualsSign => self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeValue)),
53                _ => unexpected_token!(t)
54            },
55
56            OpeningTagSubstate::InsideAttributeValue => self.read_attribute_value(t, |this, value| {
57                let name = this.data.take_attr_name().unwrap();  // unwrap() will always succeed here
58
59                // check that no attribute with such name is already present
60                // if there is one, XML is not well-formed
61                if this.data.attributes.iter().find(|a| a.name == name).is_some() {  // TODO: looks bad
62                    // TODO: ideally this error should point to the beginning of the attribute,
63                    // TODO: not the end of its value
64                    Some(self_error!(this; "Attribute '{}' is redefined", name))
65                } else {
66                    match name.prefix_ref() {
67                        // declaring a new prefix; it is sufficient to check prefix only
68                        // because "xmlns" prefix is reserved
69                        Some(namespace::NS_XMLNS_PREFIX) => {
70                            let ln = &name.local_name[..];
71                            if ln == namespace::NS_XMLNS_PREFIX {
72                                Some(self_error!(this; "Cannot redefine prefix '{}'", namespace::NS_XMLNS_PREFIX))
73                            } else if ln == namespace::NS_XML_PREFIX && &value[..] != namespace::NS_XML_URI {
74                                Some(self_error!(this; "Prefix '{}' cannot be rebound to another value", namespace::NS_XML_PREFIX))
75                            } else if value.is_empty() {
76                                Some(self_error!(this; "Cannot undefine prefix '{}'", ln))
77                            } else {
78                                this.nst.put(name.local_name.clone(), value);
79                                this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag))
80                            }
81                        }
82
83                        // declaring default namespace
84                        None if &name.local_name[..] == namespace::NS_XMLNS_PREFIX =>
85                            match &value[..] {
86                                namespace::NS_XMLNS_PREFIX | namespace::NS_XML_PREFIX =>
87                                    Some(self_error!(this; "Namespace '{}' cannot be default", value)),
88                                _ => {
89                                    this.nst.put(namespace::NS_NO_PREFIX, value.clone());
90                                    this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag))
91                                }
92                            },
93
94                        // regular attribute
95                        _ => {
96                            this.data.attributes.push(OwnedAttribute {
97                                name: name.clone(),
98                                value: value
99                            });
100                            this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag))
101                        }
102                    }
103                }
104            })
105        }
106    }
107
108}