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, 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(); if this.data.attributes.iter().find(|a| a.name == name).is_some() { Some(self_error!(this; "Attribute '{}' is redefined", name))
65 } else {
66 match name.prefix_ref() {
67 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 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 _ => {
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}