Skip to content

Commit b77e2f7

Browse files
committed
feat: Add EmitSelfClosingTag field to emit EndEvent for self-closing tags
1 parent 38220ee commit b77e2f7

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

compat.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ import (
3939
// StartElement converts a byte slice to an xml.StartElement.
4040
func StartElement(b []byte) (xml.StartElement, error) {
4141
name, b := Name(b)
42-
if len(b) > 0 && b[len(b)-1] == '/' {
43-
b = b[:len(b)-1]
44-
}
4542
e := xml.StartElement{
4643
Name: xmlName(name),
4744
}
@@ -64,7 +61,7 @@ func StartElement(b []byte) (xml.StartElement, error) {
6461
func EndElement(b []byte) xml.EndElement {
6562
name, _ := Name(b)
6663
return xml.EndElement{
67-
Name: xmlName(name[1:]),
64+
Name: xmlName(name),
6865
}
6966
}
7067

example_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,39 @@ func ExampleToken() {
148148
// EndElement element
149149
// EndElement root
150150
}
151+
152+
func ExampleReader_EmitSelfClosingTag() {
153+
xmlData := `<root><element>Value</element><selfclosing/></root>`
154+
reader := strings.NewReader(xmlData)
155+
156+
r := gosax.NewReader(reader)
157+
r.EmitSelfClosingTag = true
158+
for {
159+
e, err := r.Event()
160+
if err != nil {
161+
log.Fatal(err)
162+
}
163+
if e.Type() == gosax.EventEOF {
164+
break
165+
}
166+
switch e.Type() {
167+
case gosax.EventStart:
168+
name, _ := gosax.Name(e.Bytes)
169+
fmt.Println("EventStart", string(name))
170+
case gosax.EventEnd:
171+
name, _ := gosax.Name(e.Bytes)
172+
fmt.Println("EventEnd", string(name))
173+
case gosax.EventText:
174+
fmt.Println("EventText", string(e.Bytes))
175+
default:
176+
}
177+
}
178+
// Output:
179+
// EventStart root
180+
// EventStart element
181+
// EventText Value
182+
// EventEnd element
183+
// EventStart selfclosing
184+
// EventEnd selfclosing
185+
// EventEnd root
186+
}

gosax.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ func (e Event) Type() uint8 {
6262
type Reader struct {
6363
reader byteReader
6464
state func(*Reader) (Event, error)
65+
66+
EmitSelfClosingTag bool
67+
selfClosingEnd int
6568
}
6669

6770
func NewReader(r io.Reader) *Reader {
@@ -282,7 +285,12 @@ func (r *Reader) stateInsideMarkup() (Event, error) {
282285
}
283286
if p >= 0 {
284287
if ch == '>' {
285-
r.reader.offset += offset + p + 1
288+
if r.EmitSelfClosingTag && w[offset+p-1] == '/' {
289+
r.selfClosingEnd = offset + p
290+
r.state = (*Reader).stateSelfClosingTag
291+
} else {
292+
r.reader.offset += offset + p + 1
293+
}
286294
return Event{
287295
Bytes: w[:offset+p+1],
288296
value: EventStart,
@@ -312,6 +320,16 @@ func (r *Reader) stateInsideMarkup() (Event, error) {
312320
}
313321
}
314322

323+
func (r *Reader) stateSelfClosingTag() (Event, error) {
324+
r.state = (*Reader).stateInsideText
325+
w := r.reader.window()
326+
r.reader.offset += r.selfClosingEnd + 1
327+
return Event{
328+
Bytes: w[:r.selfClosingEnd+1],
329+
value: EventEnd,
330+
}, nil
331+
}
332+
315333
func (r *Reader) stateDone() (Event, error) {
316334
return Event{
317335
value: EventEOF,
@@ -346,9 +364,15 @@ func Name(b []byte) ([]byte, []byte) {
346364
if len(b) > 1 && b[0] == '<' {
347365
b = b[1:]
348366
}
367+
if len(b) > 1 && b[0] == '/' {
368+
b = b[1:]
369+
}
349370
if len(b) > 1 && b[len(b)-1] == '>' {
350371
b = b[:len(b)-1]
351372
}
373+
if len(b) > 1 && b[len(b)-1] == '/' {
374+
b = b[:len(b)-1]
375+
}
352376
for i, c := range b {
353377
if whitespace[c] {
354378
return b[:i], b[i+1:]

0 commit comments

Comments
 (0)