readStartTag reads a start tag.
()
| 224 | |
| 225 | // readStartTag reads a start tag. |
| 226 | func (d *Decoder) readStartTag() (*StartElement, bool) { |
| 227 | // Discard '<' |
| 228 | if !d.discard(1) { |
| 229 | return nil, false |
| 230 | } |
| 231 | |
| 232 | name, ok := d.readNSName() |
| 233 | if !ok { |
| 234 | if d.err == nil { |
| 235 | d.setSyntaxErrorf("expected name after <") |
| 236 | } |
| 237 | return nil, false |
| 238 | } |
| 239 | |
| 240 | var ( |
| 241 | attrs []*Attribute |
| 242 | selfClosing bool |
| 243 | ) |
| 244 | |
| 245 | // Read attributes |
| 246 | for { |
| 247 | if !d.skipSpaces() { |
| 248 | return nil, false |
| 249 | } |
| 250 | |
| 251 | b, ok := d.mustReadByte() |
| 252 | if !ok { |
| 253 | return nil, false |
| 254 | } |
| 255 | |
| 256 | if b == '/' { |
| 257 | // Self-closing tag |
| 258 | b, ok = d.mustReadByte() |
| 259 | if !ok { |
| 260 | return nil, false |
| 261 | } |
| 262 | if b != '>' { |
| 263 | d.setSyntaxErrorf("expected '>' at the end of self-closing tag, got %q", b) |
| 264 | return nil, false |
| 265 | } |
| 266 | |
| 267 | selfClosing = true |
| 268 | |
| 269 | break |
| 270 | } |
| 271 | |
| 272 | if b == '>' { |
| 273 | // End of start tag |
| 274 | break |
| 275 | } |
| 276 | |
| 277 | // Unread the byte for further processing |
| 278 | d.unreadByte(b) |
| 279 | |
| 280 | // Read attribute name |
| 281 | attrName, ok := d.readNSName() |
| 282 | if !ok { |
| 283 | if d.err == nil { |
no test coverage detected